Pointers C-错误为;free():无效的下一个大小(正常)";
我就是找不到造成这个问题的原因Pointers C-错误为;free():无效的下一个大小(正常)";,pointers,gdb,valgrind,sigabrt,Pointers,Gdb,Valgrind,Sigabrt,我就是找不到造成这个问题的原因 MYSQL *startup(unsigned char *path_to_file, int size_of_path) { MYSQL *con; bool path_is_file = false; bool path_is_directory = false; FILE *startup_file; int i; unsigned char buffer[LINEBUFFERSIZE]; unsigned char string[LINEBUFFERSIZ
MYSQL *startup(unsigned char *path_to_file, int size_of_path) {
MYSQL *con;
bool path_is_file = false;
bool path_is_directory = false;
FILE *startup_file;
int i;
unsigned char buffer[LINEBUFFERSIZE];
unsigned char string[LINEBUFFERSIZE];
unsigned char c;
//Allocate memory for the new file path
unsigned char *path;
path = (unsigned char *) malloc(size_of_path);
if(path == NULL)
error("Could not allocate memory for path to file.\nIn startup()\n");
//Check if startup file exists or if it is a directory
//Bug is somewehre here!!!!
struct stat s;
printf("%s", path_to_file);
if(stat(path_to_file, &s) == 0) {
if(s.st_mode & S_IFDIR) {
//It's a directory
path_is_directory = true;
//Add the standard startup file name to the directory
path = (unsigned char *) realloc(path, size_of_path + sizeof(STARTUP_FILE));
if(path == NULL)
error("Could not reallocate memory for variable path.\nIn startup()\n");
//Put the strings together
sprintf(path, "%s/%s", path_to_file, STARTUP_FILE);
}
else if(s.st_mode & S_IFREG) {
//It's a file
path_is_file = true;
path = path_to_file;
}//End else if
else //Someting else. abort
error("Given file is neither file or directory.\nIn startup()\n");
}
else //Error
error("Error in looking up type of path.\nIn startup()\n");;
//Check if the startup file exists
fprintf(stderr, "%s\n", path);
if((startup_file = fopen(path, "r")) == NULL) {
//File does not exist, create a basics one for the user to modify
if((startup_file = fopen(path, "w+")) == NULL)
error("Could not create the startup file.\n");
//Write the standard text to the new file, so the user can modify it
//sizeof(STARTUP_FILE_TEXT)-1 as gedit cries if there is a terminator at the end
fwrite(STARTUP_FILE_TEXT, sizeof(STARTUP_FILE_TEXT[0]), sizeof(STARTUP_FILE_TEXT)-1, startup_file);
}//End outer if
//Read from the startup file and find out which tables and database are needed and may have to be created
//While loop will run although if file was just created, fix it
section current;
while(fgets(buffer, sizeof(buffer), startup_file) != NULL) {
if(strcmp(buffer, "[DATABASES]")) {
//Every line now should contain the name of dbs, until new section
current = DATABASES;
}
else if(strcmp(buffer, "[TABLES]")) {
//Every line now should contain the name of dbs, until new section
current = TABLES;
}
else {
//Read the lines and create the table or database
//Ignore everything behind #
//Just numbers and letters are allowed
//Read one line and save it into buffer
//What happens, if the line exceeds buffer length and is split into to?
//Process every character, but do not exceed the buffers limit (also save one for the '\0' termiantor)
for(i = 0; i < (sizeof(buffer)-1); i++) {
//Allowed characters are: A-Z, a-z, 0-9, dash, underscore and space
//Read until '\n' or '#' or if not allowed characters are used print error and do not use it
c = buffer[i];
if(isalnum(c) || (c == '-') || (c == '_') || (c == ' ')) {
//Correct
string[i] = c;
}//End if
else if(c == '\n' || c == '\0') {
//End of line or end of string, not checking for EOF as fgets already does it \
and it would requried the int data type
break;
}//End else if
else {
//Wrong, stop
printf("Wrong character used in setup file.\nWrong characters was: %c\n", c);
break;
}//End else
}//End for
//Add terminator at the end
string[i] = '\0';
//Create table or database
switch(current) {
case DATABASES:
create_db(string, sizeof(string));
break;
case TABLES:
break;
default:
break;
}//End switch
}
}//End while
//Create db and then open the database as a specific user
//create_db();
con = open_db("user1", "passwd", "Vocables");
//Clean up
fclose(startup_file);
free(path);
return con;
}
在gdb中执行单行时,您会在错误发生之前缩短:
26 path_is_directory = true;
(gdb) n
28 path = (unsigned char *) realloc(path, size_of_path + sizeof(STARTUP_FILE));
(gdb) n
29 if(path == NULL)
(gdb) n
32 sprintf(path, "%s/%s", path_to_file, STARTUP_FILE);
(gdb) n
51 fprintf(stderr, "%s\n", path);
(gdb) n
/home/linux/Cloud/Decrypted/Porifera-Server//startup.txt
52 if((startup_file = fopen(path, "r")) == NULL) {
(gdb) n
当我在第52行之后执行下一行时,问题就出现了
使用“valgrind--leak check=yes./Porifera Server 8080~/Cloud/Decrypted/Porifera Server”,它实际上运行正常。但却有一大堆“错误”:
我就是找不到它;其他出现类似错误的人要么在
fopen
函数的文件路径中有“\n”,要么没有初始化ptr,但试图释放它。自上次运行以来,我没有接触过任何ptr自由功能,目前我还没有找到导致此问题的ptr。当遇到错误时,请从1开始。第一,它可能是以下错误的原因
MYSQL *startup(unsigned char *path_to_file, int size_of_path) {
MYSQL *con;
bool path_is_file = false;
bool path_is_directory = false;
FILE *startup_file;
int i;
unsigned char buffer[LINEBUFFERSIZE];
unsigned char string[LINEBUFFERSIZE];
unsigned char c;
//Allocate memory for the new file path
unsigned char *path;
path = (unsigned char *) malloc(size_of_path);
if(path == NULL)
error("Could not allocate memory for path to file.\nIn startup()\n");
//Check if startup file exists or if it is a directory
//Bug is somewehre here!!!!
struct stat s;
printf("%s", path_to_file);
if(stat(path_to_file, &s) == 0) {
if(s.st_mode & S_IFDIR) {
//It's a directory
path_is_directory = true;
//Add the standard startup file name to the directory
path = (unsigned char *) realloc(path, size_of_path + sizeof(STARTUP_FILE));
if(path == NULL)
error("Could not reallocate memory for variable path.\nIn startup()\n");
//Put the strings together
sprintf(path, "%s/%s", path_to_file, STARTUP_FILE);
}
else if(s.st_mode & S_IFREG) {
//It's a file
path_is_file = true;
path = path_to_file;
}//End else if
else //Someting else. abort
error("Given file is neither file or directory.\nIn startup()\n");
}
else //Error
error("Error in looking up type of path.\nIn startup()\n");;
//Check if the startup file exists
fprintf(stderr, "%s\n", path);
if((startup_file = fopen(path, "r")) == NULL) {
//File does not exist, create a basics one for the user to modify
if((startup_file = fopen(path, "w+")) == NULL)
error("Could not create the startup file.\n");
//Write the standard text to the new file, so the user can modify it
//sizeof(STARTUP_FILE_TEXT)-1 as gedit cries if there is a terminator at the end
fwrite(STARTUP_FILE_TEXT, sizeof(STARTUP_FILE_TEXT[0]), sizeof(STARTUP_FILE_TEXT)-1, startup_file);
}//End outer if
//Read from the startup file and find out which tables and database are needed and may have to be created
//While loop will run although if file was just created, fix it
section current;
while(fgets(buffer, sizeof(buffer), startup_file) != NULL) {
if(strcmp(buffer, "[DATABASES]")) {
//Every line now should contain the name of dbs, until new section
current = DATABASES;
}
else if(strcmp(buffer, "[TABLES]")) {
//Every line now should contain the name of dbs, until new section
current = TABLES;
}
else {
//Read the lines and create the table or database
//Ignore everything behind #
//Just numbers and letters are allowed
//Read one line and save it into buffer
//What happens, if the line exceeds buffer length and is split into to?
//Process every character, but do not exceed the buffers limit (also save one for the '\0' termiantor)
for(i = 0; i < (sizeof(buffer)-1); i++) {
//Allowed characters are: A-Z, a-z, 0-9, dash, underscore and space
//Read until '\n' or '#' or if not allowed characters are used print error and do not use it
c = buffer[i];
if(isalnum(c) || (c == '-') || (c == '_') || (c == ' ')) {
//Correct
string[i] = c;
}//End if
else if(c == '\n' || c == '\0') {
//End of line or end of string, not checking for EOF as fgets already does it \
and it would requried the int data type
break;
}//End else if
else {
//Wrong, stop
printf("Wrong character used in setup file.\nWrong characters was: %c\n", c);
break;
}//End else
}//End for
//Add terminator at the end
string[i] = '\0';
//Create table or database
switch(current) {
case DATABASES:
create_db(string, sizeof(string));
break;
case TABLES:
break;
default:
break;
}//End switch
}
}//End while
//Create db and then open the database as a specific user
//create_db();
con = open_db("user1", "passwd", "Vocables");
//Clean up
fclose(startup_file);
free(path);
return con;
}
==17917== Invalid write of size 8
==17917== at 0x5E53E04: __GI_mempcpy (in /usr/lib/libc-2.21.so)
==17917== by 0x5E44BDD: _IO_default_xsputn (in /usr/lib/libc-2.21.so)
==17917== by 0x5E18C61: vfprintf (in /usr/lib/libc-2.21.so)
==17917== by 0x5E3AC2A: vsprintf (in /usr/lib/libc-2.21.so)
==17917== by 0x5E1F266: sprintf (in /usr/lib/libc-2.21.so)
==17917== by 0x401647: startup (server_func.c:32)
==17917== by 0x4012BB: main (server.c:23)
==17917== Address 0x6c8709e is 14 bytes inside a block of size 20 alloc'd
==17917== at 0x4C2C29E: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==17917== by 0x40160B: startup (server_func.c:28)
==17917== by 0x4012BB: main (server.c:23)
在这个堆栈跟踪中,interesting片段是程序的代码,因为我们可以假设运行时/标准库中的代码可以工作
Valgrind在这里告诉您两件事:
path=(unsigned char*)realloc(路径,路径的大小+sizeof(启动文件))代码>
第32行:sprintf(路径,“%s/%s”,路径到文件,启动文件)代码>
所以在第28行中,您没有为“/”分隔符分配空间,也可能没有为nul终止符分配空间
您还需要确保路径的size\u
是正确的,并且sizeof(STARTUP\u FILE)
为您提供了正确的大小,如果STARTUP\u FILE
是一个字符数组,它将提供正确的大小,但是如果它是一个字符指针,它将是错误的。也许您需要使用strlen(启动文件)
假设size\u of_path
是正确的,您可能需要将缓冲区大小计算为size\u of_path+strlen(启动文件)+2
这表示您使用realloc()创建的缓冲区太小,因此下面的sprintf(路径,“%s/%s”,路径到启动文件,启动文件)代码>可能会破坏内存。但是,我们不知道sizeof(STARTUP_FILE)或size_of_path是什么,也不知道它们是否正确-也许STARTUP_FILE是一个char*但您假设它是一个数组。不过,您需要为“/”和nul终止符分配空间。是的,您是对的,尽管我确信分配了足够的内存。但这解决了问题。您能告诉我您是如何发现的吗?或者引用gdb或valgrind输出的行,以便下次我知道,因为我仍然是初学者。:-)我使用了sizeof(argv[2]),但它返回的长度绝对错误。有没有办法找出命令行参数的大小?是的,strlen(argv[2])给出了长度,不包括nul终止符。H,感谢您的解释:-)当我使用sizeof(argv[2])来找出它时,路径的大小是不正确的,但它是一个字符指针,所以我将它改为strlen(argv[2]):-)
==17917== Invalid write of size 8
==17917== at 0x5E53E04: __GI_mempcpy (in /usr/lib/libc-2.21.so)
==17917== by 0x5E44BDD: _IO_default_xsputn (in /usr/lib/libc-2.21.so)
==17917== by 0x5E18C61: vfprintf (in /usr/lib/libc-2.21.so)
==17917== by 0x5E3AC2A: vsprintf (in /usr/lib/libc-2.21.so)
==17917== by 0x5E1F266: sprintf (in /usr/lib/libc-2.21.so)
==17917== by 0x401647: startup (server_func.c:32)
==17917== by 0x4012BB: main (server.c:23)
==17917== Address 0x6c8709e is 14 bytes inside a block of size 20 alloc'd
==17917== at 0x4C2C29E: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==17917== by 0x40160B: startup (server_func.c:28)
==17917== by 0x4012BB: main (server.c:23)