使用char指针和realloc随机获取segfault

时间:2017-09-21 01:12:36

标签: c pointers malloc realloc

这是令我头疼的代码:

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

Paste to full valgrind test

@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 >= 0i + 1 < str_sizei + j < str_size来纠正它们。现在程序运行正常。

但是,我仍然不明白的是,我的代码的第13行和第25行之间可能发生分段错误(这是我上面粘贴的代码),如果问题出现在141行和178,以及如何使用相同的输入随机发生此问题。

@edit:另一点是,正如我所评论的,当我将输入变量声明为char input[600]时,没有发生任何分段错误问题。

0 个答案:

没有答案