条件跳转或移动取决于未初始化的值和大小的无效写入
Conditional jump or move depends on uninitialised value and Invalid write of size
我有一些与内存有关的奇怪问题。这是我的代码:
#include <iostream>
#include <string.h>
#include <cstdlib>
#include <stdio.h>
struct Pair{
char *key;
unsigned long long int value;
};
int main()
{
Pair p;
char string[256];
char path[100];
int i;
int l;
std::cout<<"ENTER THE DIRECTORY"<<std::endl;
std::cin>>path;
FILE *f = fopen(path,"wb");
for (i = 0; i<5; i++) {
std::cin>>string;
p.key = new char[strlen(string)];
l = strlen(p.key);
std::cin>>p.value;
strcpy(p.key,string);
if (!fwrite(&l,sizeof(int),1,f))
perror("ERROR: ");
if (!fwrite(p.key, sizeof(char),l,f))
perror("ERROR: ");
if (!fwrite(&p.value, sizeof(unsigned long long int),1,f))
perror("ERROR: ");
std::cout<<p.key<<" "<<p.value<<std::endl;
delete [] p.key;
}
fclose(f);
f = fopen(path,"rb");
for (i = 0; i<5; i++) {
if (!fread(&l,sizeof(int),1,f))
perror("ERROR: ");
p.key = new char[l];
if (!fread(p.key,sizeof(char),l,f))
perror("ERROR: ");
if (!fread(&p.value, sizeof(unsigned long long int),1,f))
perror("ERROR: ");
std::cout<<p.key<<" "<<p.value<<std::endl;
delete [] p.key;
}
fclose(f);
return 0;
}
但是 valgrind 说,条件跳转或移动取决于 l = strlen(p.key) 中未初始化的值;更重要的是,从文件读取后没有 valgrind 它不显示键,只显示值。
==10157== Conditional jump or move depends on uninitialised value(s)
==10157== at 0x402D3EB: strlen (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==10157== by 0x8048A84: main (main.cpp:25)
==10157==
==10157== Invalid write of size 1
==10157== at 0x402D506: strcpy (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==10157== by 0x8048AB6: main (main.cpp:27)
==10157== Address 0x434c1bc is 0 bytes after a block of size 4 alloc'd
==10157== at 0x402ADFC: operator new[](unsigned int) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==10157== by 0x8048A74: main (main.cpp:24)
如果我将 l = strlen(p.key) 更改为 l = strlen(string) valgrind 说
==10030== Invalid write of size 1
==10030== at 0x402D506: strcpy (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==10030== by 0x8048AB9: main (main.cpp:27)
==10030== Address 0x434c1bb is 0 bytes after a block of size 3 alloc'd
==10030== at 0x402ADFC: operator new[](unsigned int) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==10030== by 0x8048A74: main (main.cpp:24)
==10030==
==10030== Invalid read of size 1
==10030== at 0x402D3F3: strlen (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==10030== by 0x40D33E4: std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*) (in /usr/lib/i386-linux-gnu/libstdc++.so.6.0.19)
==10030== by 0x8048B85: main (main.cpp:34)
==10030== Address 0x434c1bb is 0 bytes after a block of size 3 alloc'd
==10030== at 0x402ADFC: operator new[](unsigned int) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==10030== by 0x8048A74: main (main.cpp:24)
strcpy 函数也是如此。
我还尝试通过 memset 使用 '\0' 初始化 p.key,但 valgrind 写入
==10562== Invalid write of size 4
==10562== at 0x403087D: memset (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
...
valgrind: m_mallocfree.c:277 (mk_plain_bszB): Assertion 'bszB != 0' failed.
valgrind: This is probably caused by your program erroneously writing past the
end of a heap block and corrupting heap metadata. If you fix any
invalid writes reported by Memcheck, this assertion failure will
probably go away. Please try that before reporting this as a bug.
所以,为什么我在这个简单的代码中有这些问题,他们的决定有哪些可能的方式,请帮助我。
问题 1
p.key = new char[strlen(string)];
l = strlen(p.key);
您正在使用未初始化的 p.key
。由于 strlen
依赖于空终止字符数组,因此调用 strlen(p.key)
会导致未定义的行为。
问题2
strcpy(p.key,string);
也是一个问题。您没有分配足够的内存来保存 p.key
中的终止空字符。您需要使用:
p.key = new char[strlen(string)+1];
// ^^ Need the additional character
问题3
下面几行适合恢复文件的内容。但是,该字符串不是空终止的。
p.key = new char[l];
if (!fread(p.key,sizeof(char),l,f))
您需要使用:
p.key = new char[l+1];
// ^^ Need the additional character
if (!fread(p.key,sizeof(char),l,f))
p.key[l] = '[=14=]`;
我有一些与内存有关的奇怪问题。这是我的代码:
#include <iostream>
#include <string.h>
#include <cstdlib>
#include <stdio.h>
struct Pair{
char *key;
unsigned long long int value;
};
int main()
{
Pair p;
char string[256];
char path[100];
int i;
int l;
std::cout<<"ENTER THE DIRECTORY"<<std::endl;
std::cin>>path;
FILE *f = fopen(path,"wb");
for (i = 0; i<5; i++) {
std::cin>>string;
p.key = new char[strlen(string)];
l = strlen(p.key);
std::cin>>p.value;
strcpy(p.key,string);
if (!fwrite(&l,sizeof(int),1,f))
perror("ERROR: ");
if (!fwrite(p.key, sizeof(char),l,f))
perror("ERROR: ");
if (!fwrite(&p.value, sizeof(unsigned long long int),1,f))
perror("ERROR: ");
std::cout<<p.key<<" "<<p.value<<std::endl;
delete [] p.key;
}
fclose(f);
f = fopen(path,"rb");
for (i = 0; i<5; i++) {
if (!fread(&l,sizeof(int),1,f))
perror("ERROR: ");
p.key = new char[l];
if (!fread(p.key,sizeof(char),l,f))
perror("ERROR: ");
if (!fread(&p.value, sizeof(unsigned long long int),1,f))
perror("ERROR: ");
std::cout<<p.key<<" "<<p.value<<std::endl;
delete [] p.key;
}
fclose(f);
return 0;
}
但是 valgrind 说,条件跳转或移动取决于 l = strlen(p.key) 中未初始化的值;更重要的是,从文件读取后没有 valgrind 它不显示键,只显示值。
==10157== Conditional jump or move depends on uninitialised value(s)
==10157== at 0x402D3EB: strlen (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==10157== by 0x8048A84: main (main.cpp:25)
==10157==
==10157== Invalid write of size 1
==10157== at 0x402D506: strcpy (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==10157== by 0x8048AB6: main (main.cpp:27)
==10157== Address 0x434c1bc is 0 bytes after a block of size 4 alloc'd
==10157== at 0x402ADFC: operator new[](unsigned int) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==10157== by 0x8048A74: main (main.cpp:24)
如果我将 l = strlen(p.key) 更改为 l = strlen(string) valgrind 说
==10030== Invalid write of size 1
==10030== at 0x402D506: strcpy (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==10030== by 0x8048AB9: main (main.cpp:27)
==10030== Address 0x434c1bb is 0 bytes after a block of size 3 alloc'd
==10030== at 0x402ADFC: operator new[](unsigned int) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==10030== by 0x8048A74: main (main.cpp:24)
==10030==
==10030== Invalid read of size 1
==10030== at 0x402D3F3: strlen (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==10030== by 0x40D33E4: std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*) (in /usr/lib/i386-linux-gnu/libstdc++.so.6.0.19)
==10030== by 0x8048B85: main (main.cpp:34)
==10030== Address 0x434c1bb is 0 bytes after a block of size 3 alloc'd
==10030== at 0x402ADFC: operator new[](unsigned int) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==10030== by 0x8048A74: main (main.cpp:24)
strcpy 函数也是如此。 我还尝试通过 memset 使用 '\0' 初始化 p.key,但 valgrind 写入
==10562== Invalid write of size 4
==10562== at 0x403087D: memset (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
...
valgrind: m_mallocfree.c:277 (mk_plain_bszB): Assertion 'bszB != 0' failed.
valgrind: This is probably caused by your program erroneously writing past the
end of a heap block and corrupting heap metadata. If you fix any
invalid writes reported by Memcheck, this assertion failure will
probably go away. Please try that before reporting this as a bug.
所以,为什么我在这个简单的代码中有这些问题,他们的决定有哪些可能的方式,请帮助我。
问题 1
p.key = new char[strlen(string)];
l = strlen(p.key);
您正在使用未初始化的 p.key
。由于 strlen
依赖于空终止字符数组,因此调用 strlen(p.key)
会导致未定义的行为。
问题2
strcpy(p.key,string);
也是一个问题。您没有分配足够的内存来保存 p.key
中的终止空字符。您需要使用:
p.key = new char[strlen(string)+1];
// ^^ Need the additional character
问题3
下面几行适合恢复文件的内容。但是,该字符串不是空终止的。
p.key = new char[l];
if (!fread(p.key,sizeof(char),l,f))
您需要使用:
p.key = new char[l+1];
// ^^ Need the additional character
if (!fread(p.key,sizeof(char),l,f))
p.key[l] = '[=14=]`;