Valgrind 报告 SIGSEGV 和未初始化值的使用
Valgrind reports SIGSEGV and use of uninitialised value
编辑:通过初始化解决的所有 valgrind 错误 i
。
我正在处理字符串;从文件中读取字符串,使用 strsep()
分隔它们,使用 atol()
将它们转换为 int。我的代码在 gcc 上编译并且运行没有错误,但是当用 valgrind 检查时我得到了标题中提到的错误。
我正在尝试使用文本文件中的 int 值填充 two-dimensional 数组 grid[20][20]
。文本文件包含由空格分隔的数字行,例如 20 81 65 07 54 72 13 28 66 95 00 20 00 84 06 30 85 43 15 73\n
我的代码,(不包括所有的文件IO)如下。 (请注意,我确实正确处理了文件:检查 fopen
的结果,以 fclose
结束)。
更新代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define STR_LEN 20
#define NUM_LINES 20
#define MAX_SIZE 100
int main(void){
char input_str[MAX_SIZE]; //string to hold lines read from file
char * str_array[STR_LEN]; //array of strings to split the lines into
int grid[20][20];
char * token, *str, *tofree;
int line;
for (line = 0; line < NUM_LINES; ++line){ //for every line in the file
if (fgets(input_str, MAX_SIZE, fp)!=NULL){ //read the file's line into input_str
tofree = str = strdup(input_str); //set str to copy of input_string, and tofree to point to beginning of str's memory, to free later
int i = 0;
while ((token = strsep(&str, " "))){ //split str on " ", keeping everything in between in token
str_array[i] = token; //add token to str_array
++i;
}
for (i = 0; i < STR_LEN; ++i){
grid[line][i] = atol(str_array[i]); //convert strings to int and store in num_array
printf("grid[%d][%d]: %d\n", line, i, grid[line][i]);
}
free(tofree); //free str by freeing tofree, as tofree points to str's memory
}
}
printf("%d", grid[0][0]);
return 0;
}
我用 gcc -Wall -g -c myfile.c
编译这段代码。它编译和运行都很好,没有错误。在将值传递给 grid
之后使用 printf()
检查值会显示所有正确的值。 然而,代码中的最后一个 printf()
显示 grid[0][0]
包含垃圾,即使它之前是正确的。事实上,grid[0]
中的所有元素都已损坏。
运行 valgrind valgrind --leak-check=full --track-origins=yes --dsymutil=yes --show-leak-kinds=all ./productGrid.elf
给我
$ valgrind --leak-check=full --track-origins=yes --dsymutil=yes --show-leak-kinds=all ./productGrid.elf
==2252== Command: ./productGrid.elf
==2252==
==2252== Use of uninitialised value of size 4
==2252== at 0x106EC: main (in /home/jesse/C/Proj. Euler/productGrid.elf)
==2252== Uninitialised value was created by a stack allocation
==2252== at 0x10656: main (in /home/jesse/C/Proj. Euler/productGrid.elf)
==2252==
==2252== Invalid write of size 4
==2252== at 0x106EC: main (in /home/jesse/C/Proj. Euler/productGrid.elf)
==2252== Address 0x7e2b6c38 is not stack'd, malloc'd or (recently) free'd
==2252==
==2252==
==2252== Process terminating with default action of signal 11 (SIGSEGV)
==2252== Access not within mapped region at address 0x7E2B6C38
==2252== at 0x106EC: main (in /home/jesse/C/Proj. Euler/productGrid.elf)
==2252== If you believe this happened as a result of a stack
==2252== overflow in your program's main thread (unlikely but
==2252== possible), you can try to increase the size of the
==2252== main thread stack using the --main-stacksize= flag.
==2252== The main thread stack size used in this run was 8388608.
==2252==
==2252== HEAP SUMMARY:
==2252== in use at exit: 413 bytes in 2 blocks
==2252== total heap usage: 3 allocs, 1 frees, 4,509 bytes allocated
==2252==
==2252== 61 bytes in 1 blocks are still reachable in loss record 1 of 2
==2252== at 0x483E380: malloc (vg_replace_malloc.c:299)
==2252== by 0x48E188B: strdup (strdup.c:42)
==2252== by 0x106C9: main (in /home/jesse/C/Proj. Euler/productGrid.elf)
==2252==
==2252== 352 bytes in 1 blocks are still reachable in loss record 2 of 2
==2252== at 0x483E380: malloc (vg_replace_malloc.c:299)
==2252== by 0x48D11F3: __fopen_internal (iofopen.c:69)
==2252== by 0x10681: main (in /home/jesse/C/Proj. Euler/productGrid.elf)
==2252==
==2252== LEAK SUMMARY:
==2252== definitely lost: 0 bytes in 0 blocks
==2252== indirectly lost: 0 bytes in 0 blocks
==2252== possibly lost: 0 bytes in 0 blocks
==2252== still reachable: 413 bytes in 2 blocks
==2252== suppressed: 0 bytes in 0 blocks
==2252==
==2252== For counts of detected and suppressed errors, rerun with: -v
==2252== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 6 from 3)
Segmentation fault
对我做错了什么有什么想法吗?
i
在此处未初始化使用:
str_array[i] = token;
++i;
注:
如果您使用符号编译(GCC 的选项 -g
),则 Valgrind 会使用对源代码行的引用来注释其日志记录。
我无法评论,所以我 post 一个新的答案。正如@alk 所说,i
它是未初始化的,如果您只是在定义中对其进行初始化,则 while 将不起作用。使用一个for(;;)
,因为你需要赋值。
如果仍有问题,请更新您的代码。
你应该在开头初始化 i。
另外关于这段代码:
while ((token = strsep(&str, " "))){
str_array[i] = token; //add token to str_array
++i;
}
for (i = 0; i < STR_LEN; ++i){
grid[line][i] = atol(str_array[i]);
printf("grid[%d][%d]: %d\n", line, i, grid[line][i]);
}
如果要将 i 归零,为什么要计算 i?也许你应该使用不同的计数器并循环直到这个而不是 STR_LEN.
希望对您有所帮助。
编辑:通过初始化解决的所有 valgrind 错误 i
。
我正在处理字符串;从文件中读取字符串,使用 strsep()
分隔它们,使用 atol()
将它们转换为 int。我的代码在 gcc 上编译并且运行没有错误,但是当用 valgrind 检查时我得到了标题中提到的错误。
我正在尝试使用文本文件中的 int 值填充 two-dimensional 数组 grid[20][20]
。文本文件包含由空格分隔的数字行,例如 20 81 65 07 54 72 13 28 66 95 00 20 00 84 06 30 85 43 15 73\n
我的代码,(不包括所有的文件IO)如下。 (请注意,我确实正确处理了文件:检查 fopen
的结果,以 fclose
结束)。
更新代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define STR_LEN 20
#define NUM_LINES 20
#define MAX_SIZE 100
int main(void){
char input_str[MAX_SIZE]; //string to hold lines read from file
char * str_array[STR_LEN]; //array of strings to split the lines into
int grid[20][20];
char * token, *str, *tofree;
int line;
for (line = 0; line < NUM_LINES; ++line){ //for every line in the file
if (fgets(input_str, MAX_SIZE, fp)!=NULL){ //read the file's line into input_str
tofree = str = strdup(input_str); //set str to copy of input_string, and tofree to point to beginning of str's memory, to free later
int i = 0;
while ((token = strsep(&str, " "))){ //split str on " ", keeping everything in between in token
str_array[i] = token; //add token to str_array
++i;
}
for (i = 0; i < STR_LEN; ++i){
grid[line][i] = atol(str_array[i]); //convert strings to int and store in num_array
printf("grid[%d][%d]: %d\n", line, i, grid[line][i]);
}
free(tofree); //free str by freeing tofree, as tofree points to str's memory
}
}
printf("%d", grid[0][0]);
return 0;
}
我用 gcc -Wall -g -c myfile.c
编译这段代码。它编译和运行都很好,没有错误。在将值传递给 grid
之后使用 printf()
检查值会显示所有正确的值。 然而,代码中的最后一个 printf()
显示 grid[0][0]
包含垃圾,即使它之前是正确的。事实上,grid[0]
中的所有元素都已损坏。
运行 valgrind valgrind --leak-check=full --track-origins=yes --dsymutil=yes --show-leak-kinds=all ./productGrid.elf
给我
$ valgrind --leak-check=full --track-origins=yes --dsymutil=yes --show-leak-kinds=all ./productGrid.elf
==2252== Command: ./productGrid.elf
==2252==
==2252== Use of uninitialised value of size 4
==2252== at 0x106EC: main (in /home/jesse/C/Proj. Euler/productGrid.elf)
==2252== Uninitialised value was created by a stack allocation
==2252== at 0x10656: main (in /home/jesse/C/Proj. Euler/productGrid.elf)
==2252==
==2252== Invalid write of size 4
==2252== at 0x106EC: main (in /home/jesse/C/Proj. Euler/productGrid.elf)
==2252== Address 0x7e2b6c38 is not stack'd, malloc'd or (recently) free'd
==2252==
==2252==
==2252== Process terminating with default action of signal 11 (SIGSEGV)
==2252== Access not within mapped region at address 0x7E2B6C38
==2252== at 0x106EC: main (in /home/jesse/C/Proj. Euler/productGrid.elf)
==2252== If you believe this happened as a result of a stack
==2252== overflow in your program's main thread (unlikely but
==2252== possible), you can try to increase the size of the
==2252== main thread stack using the --main-stacksize= flag.
==2252== The main thread stack size used in this run was 8388608.
==2252==
==2252== HEAP SUMMARY:
==2252== in use at exit: 413 bytes in 2 blocks
==2252== total heap usage: 3 allocs, 1 frees, 4,509 bytes allocated
==2252==
==2252== 61 bytes in 1 blocks are still reachable in loss record 1 of 2
==2252== at 0x483E380: malloc (vg_replace_malloc.c:299)
==2252== by 0x48E188B: strdup (strdup.c:42)
==2252== by 0x106C9: main (in /home/jesse/C/Proj. Euler/productGrid.elf)
==2252==
==2252== 352 bytes in 1 blocks are still reachable in loss record 2 of 2
==2252== at 0x483E380: malloc (vg_replace_malloc.c:299)
==2252== by 0x48D11F3: __fopen_internal (iofopen.c:69)
==2252== by 0x10681: main (in /home/jesse/C/Proj. Euler/productGrid.elf)
==2252==
==2252== LEAK SUMMARY:
==2252== definitely lost: 0 bytes in 0 blocks
==2252== indirectly lost: 0 bytes in 0 blocks
==2252== possibly lost: 0 bytes in 0 blocks
==2252== still reachable: 413 bytes in 2 blocks
==2252== suppressed: 0 bytes in 0 blocks
==2252==
==2252== For counts of detected and suppressed errors, rerun with: -v
==2252== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 6 from 3)
Segmentation fault
对我做错了什么有什么想法吗?
i
在此处未初始化使用:
str_array[i] = token;
++i;
注:
如果您使用符号编译(GCC 的选项 -g
),则 Valgrind 会使用对源代码行的引用来注释其日志记录。
我无法评论,所以我 post 一个新的答案。正如@alk 所说,i
它是未初始化的,如果您只是在定义中对其进行初始化,则 while 将不起作用。使用一个for(;;)
,因为你需要赋值。
如果仍有问题,请更新您的代码。
你应该在开头初始化 i。
另外关于这段代码:
while ((token = strsep(&str, " "))){
str_array[i] = token; //add token to str_array
++i;
}
for (i = 0; i < STR_LEN; ++i){
grid[line][i] = atol(str_array[i]);
printf("grid[%d][%d]: %d\n", line, i, grid[line][i]);
}
如果要将 i 归零,为什么要计算 i?也许你应该使用不同的计数器并循环直到这个而不是 STR_LEN.
希望对您有所帮助。