这是令我头疼的代码:
char *input, ch;
int str_size = 0;
input = malloc(sizeof(char));
while((ch = getchar()) != EOF){
if (ch >= 32 || ch == '\n') {
if (ch == '\n')
line_count++;
input[str_size++] = ch;
input = realloc(input, sizeof(char) * (str_size + 1));
printf("%c", ch);
}
}
input[str_size] = '\0';
我在C中做了一个JSON解析器,我的输入是:
{"":{"":2}}
{"": [,,,,,2, null, true]}
{"a":+}
问题是我的代码总是在第二行的末尾随机获得段错误问题,有时它会完美地运行整个程序:
Sergios-MacBook-Pro-2:Trab3-Parser Sergio$ ./parser < casos/1.in
{"":{"":2}}
{"": [,,,,,2, null, true]}
Segmentation fault: 11
Sergios-MacBook-Pro-2:Trab3-Parser Sergio$ ./parser < casos/1.in
{"":{"":2}}
{"": [,,,,,2, null, true]}
Segmentation fault: 11
Sergios-MacBook-Pro-2:Trab3-Parser Sergio$ ./parser < casos/1.in
{"":{"":2}}
{"": [,,,,,2, null, true]}
Segmentation fault: 11
Sergios-MacBook-Pro-2:Trab3-Parser Sergio$ ./parser < casos/1.in
{"":{"":2}}
{"": [,,,,,2, null, true]}
Segmentation fault: 11
Sergios-MacBook-Pro-2:Trab3-Parser Sergio$ ./parser < casos/1.in
{"":{"":2}}
{"": [,,,,,2, null, true]}
{"a":+}Error line 3
Number of Objects: 3
Number of Arrays: 1
Number of Pairs: 3
Number of Strings: 4
Number of Numbers: 2
Number of Trues: 1
Number of Falses: 0
Number of Nulls: 1
我做错了什么? Ps:是的,我在代码末尾释放输入。
@edit:Link to download the input
这是运行valgrind之后的结果:
Sergios-MacBook-Pro-2:Trab3-Parser Sergio$ valgrind ./parser < casos/1.in
==20350== Memcheck, a memory error detector
==20350== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==20350== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==20350== Command: ./parser
==20350==
==20350== Syscall param msg->desc.port.name points to uninitialised byte(s)
==20350== at 0x1003AA34A: mach_msg_trap (in /usr/lib/system/libsystem_kernel.dylib)
==20350== by 0x1003A9796: mach_msg (in /usr/lib/system/libsystem_kernel.dylib)
==20350== by 0x1003A3485: task_set_special_port (in /usr/lib/system/libsystem_kernel.dylib)
==20350== by 0x10053F10E: _os_trace_create_debug_control_port (in /usr/lib/system/libsystem_trace.dylib)
==20350== by 0x10053F458: _libtrace_init (in /usr/lib/system/libsystem_trace.dylib)
==20350== by 0x1000A89DF: libSystem_initializer (in /usr/lib/libSystem.B.dylib)
==20350== by 0x10001AA1A: ImageLoaderMachO::doModInitFunctions(ImageLoader::LinkContext const&) (in /usr/lib/dyld)
==20350== by 0x10001AC1D: ImageLoaderMachO::doInitialization(ImageLoader::LinkContext const&) (in /usr/lib/dyld)
==20350== by 0x1000164A9: ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int, char const*, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&) (in /usr/lib/dyld)
==20350== by 0x100016440: ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int, char const*, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&) (in /usr/lib/dyld)
==20350== by 0x100015523: ImageLoader::processInitializers(ImageLoader::LinkContext const&, unsigned int, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&) (in /usr/lib/dyld)
==20350== by 0x1000155B8: ImageLoader::runInitializers(ImageLoader::LinkContext const&, ImageLoader::InitializerTimingList&) (in /usr/lib/dyld)
==20350== Address 0x10488dd6c is on thread 1's stack
==20350== in frame #2, created by task_set_special_port (???:)
==20350==
==20350== Invalid read of size 1
==20350== at 0x100001C6A: main (main.c:141)
==20350== Address 0x100b5bf8f is 1 bytes before a block of size 50 alloc'd
==20350== at 0x10009AFC4: realloc (in /usr/local/Cellar/valgrind/3.13.0/lib/valgrind/vgpreload_memcheck-amd64-darwin.so)
==20350== by 0x1000014A8: main (main.c:21)
==20350==
==20350== Invalid read of size 1
==20350== at 0x100001FFE: main (main.c:178)
==20350== Address 0x100b5bfc2 is 0 bytes after a block of size 50 alloc'd
==20350== at 0x10009AFC4: realloc (in /usr/local/Cellar/valgrind/3.13.0/lib/valgrind/vgpreload_memcheck-amd64-darwin.so)
==20350== by 0x1000014A8: main (main.c:21)
==20350==
==20350== Conditional jump or move depends on uninitialised value(s)
==20350== at 0x100002005: main (main.c:178)
==20350==
==20350==
==20350== Process terminating with default action of signal 11 (SIGSEGV)
==20350== Access not within mapped region at address 0x100F51000
==20350== at 0x100001FFE: main (main.c:178)
==20350== If you believe this happened as a result of a stack
==20350== overflow in your program's main thread (unlikely but
==20350== possible), you can try to increase the size of the
==20350== main thread stack using the --main-stacksize= flag.
==20350== The main thread stack size used in this run was 8388608.
==20350==
==20350== HEAP SUMMARY:
==20350== in use at exit: 26,407 bytes in 165 blocks
==20350== total heap usage: 230 allocs, 65 frees, 33,776 bytes allocated
==20350==
==20350== LEAK SUMMARY:
==20350== definitely lost: 408 bytes in 8 blocks
==20350== indirectly lost: 6,888 bytes in 8 blocks
==20350== possibly lost: 72 bytes in 3 blocks
==20350== still reachable: 4,178 bytes in 3 blocks
==20350== suppressed: 14,861 bytes in 143 blocks
==20350== Rerun with --leak-check=full to see details of leaked memory
==20350==
==20350== For counts of detected and suppressed errors, rerun with: -v
==20350== Use --track-origins=yes to see where uninitialised values come from
==20350== ERROR SUMMARY: 4149312 errors from 4 contexts (suppressed: 4 from 4)
Segmentation fault: 11
@edit:发现内存泄漏的原因: 这些是valgrind中显示的main.c的141行和178行,如@Serge所示:
141:
if (!is_valid_non_string_char(input[i], input[i - 1], input[i + 1])) {
178:
for (j = 1; input[i + j] != ' '; j++) {}
所以,我已经通过设置条件i - 1 >= 0
,i + 1 < str_size
和i + j < str_size
来纠正它们。现在程序运行正常。
但是,我仍然不明白的是,我的代码的第13行和第25行之间可能发生分段错误(这是我上面粘贴的代码),如果问题出现在141行和178,以及如何使用相同的输入随机发生此问题。
@edit:另一点是,正如我所评论的,当我将输入变量声明为char input[600]
时,没有发生任何分段错误问题。