Может кто - нибудь помочь мне проанализировать эти результаты valgrind?


Я написал программу C на linux для обработки большого количества данных, она работает нормально большую часть времени. Но при обработке набора конкретных данных он всегда говорил мне об ошибке "ошибка сегментации", я пытался использовать gdb без успеха (см. Мой другой вопрос Как справиться с ошибкой сегментации с GDB при определенных обстоятельствах?), поэтому я попытался использовать valgrind. Он не сказал мне об ошибке "ошибка сегментации" при запуске с valgrind. Так как же найти жучка по этим вальгриндам выход?

==2441== Invalid write of size 4
==2441==    at 0x404893: nodes_term32_flush (tyn_indexer.c:227)
==2441==    by 0x407B77: tyn_exsorter_sort (tyn_exsorter.c:131)
==2441==    by 0x406DDE: tyn_build_index (tyn_indexer.c:731)
==2441==    by 0x40384F: main (tyn_indexer.c:943)
==2441==  Address 0x1233c080 is 0 bytes after a block of size 1,048,576 alloc'd
==2441==    at 0x4A074CD: malloc (vg_replace_malloc.c:236)
==2441==    by 0x406BEB: tyn_build_index (tyn_indexer.c:663)
==2441==    by 0x40384F: main (tyn_indexer.c:943)
==2441==
==2441== Invalid write of size 4
==2441==    at 0x4048D8: nodes_term32_flush (tyn_indexer.c:254)
==2441==    by 0x407B77: tyn_exsorter_sort (tyn_exsorter.c:131)
==2441==    by 0x406DDE: tyn_build_index (tyn_indexer.c:731)
==2441==    by 0x40384F: main (tyn_indexer.c:943)
==2441==  Address 0x1233c080 is 0 bytes after a block of size 1,048,576 alloc'd
==2441==    at 0x4A074CD: malloc (vg_replace_malloc.c:236)
==2441==    by 0x406BEB: tyn_build_index (tyn_indexer.c:663)
==2441==    by 0x40384F: main (tyn_indexer.c:943)
==2441==
==2441== Invalid read of size 4
==2441==    at 0x40450D: nodes_term32_flush (tyn_indexer.c:260)
==2441==    by 0x407B77: tyn_exsorter_sort (tyn_exsorter.c:131)
==2441==    by 0x406DDE: tyn_build_index (tyn_indexer.c:731)
==2441==    by 0x40384F: main (tyn_indexer.c:943)
==2441==  Address 0x1233c080 is 0 bytes after a block of size 1,048,576 alloc'd
==2441==    at 0x4A074CD: malloc (vg_replace_malloc.c:236)
==2441==    by 0x406BEB: tyn_build_index (tyn_indexer.c:663)
==2441==    by 0x40384F: main (tyn_indexer.c:943)
==2441==
==2441== Invalid read of size 4
==2441==    at 0x404878: nodes_term32_flush (tyn_indexer.c:224)
==2441==    by 0x407B77: tyn_exsorter_sort (tyn_exsorter.c:131)
==2441==    by 0x406DDE: tyn_build_index (tyn_indexer.c:731)
==2441==    by 0x40384F: main (tyn_indexer.c:943)
==2441==  Address 0x1233c080 is 0 bytes after a block of size 1,048,576 alloc'd
==2441==    at 0x4A074CD: malloc (vg_replace_malloc.c:236)
==2441==    by 0x406BEB: tyn_build_index (tyn_indexer.c:663)
==2441==    by 0x40384F: main (tyn_indexer.c:943)
==2441==
==2441== Invalid write of size 4
==2441==    at 0x40487F: nodes_term32_flush (tyn_indexer.c:224)
==2441==    by 0x407B77: tyn_exsorter_sort (tyn_exsorter.c:131)
==2441==    by 0x406DDE: tyn_build_index (tyn_indexer.c:731)
==2441==    by 0x40384F: main (tyn_indexer.c:943)
==2441==  Address 0x1233c080 is 0 bytes after a block of size 1,048,576 alloc'd
==2441==    at 0x4A074CD: malloc (vg_replace_malloc.c:236)
==2441==    by 0x406BEB: tyn_build_index (tyn_indexer.c:663)
==2441==    by 0x40384F: main (tyn_indexer.c:943)
==2441==
==2441== Invalid read of size 4
==2441==    at 0x4048BD: nodes_term32_flush (tyn_indexer.c:251)
==2441==    by 0x407B77: tyn_exsorter_sort (tyn_exsorter.c:131)
==2441==    by 0x406DDE: tyn_build_index (tyn_indexer.c:731)
==2441==    by 0x40384F: main (tyn_indexer.c:943)
==2441==  Address 0x1233c094 is not stack'd, malloc'd or (recently) free'd
==2441==
==2441== Invalid write of size 4
==2441==    at 0x4048C4: nodes_term32_flush (tyn_indexer.c:251)
==2441==    by 0x407B77: tyn_exsorter_sort (tyn_exsorter.c:131)
==2441==    by 0x406DDE: tyn_build_index (tyn_indexer.c:731)
==2441==    by 0x40384F: main (tyn_indexer.c:943)
==2441==  Address 0x1233c094 is not stack'd, malloc'd or (recently) free'd
==2441==
==2441== Invalid read of size 4
==2441==    at 0x4093A0: tyn_p4d_encode32 (tyn_coder.c:645)
==2441==    by 0x4045F0: nodes_term32_flush (tyn_indexer.c:132)
==2441==    by 0x407B77: tyn_exsorter_sort (tyn_exsorter.c:131)
==2441==    by 0x406DDE: tyn_build_index (tyn_indexer.c:731)
==2441==    by 0x40384F: main (tyn_indexer.c:943)
==2441==  Address 0x1233c080 is 0 bytes after a block of size 1,048,576 alloc'd
==2441==    at 0x4A074CD: malloc (vg_replace_malloc.c:236)
==2441==    by 0x406BEB: tyn_build_index (tyn_indexer.c:663)
==2441==    by 0x40384F: main (tyn_indexer.c:943)
==2441==
==2441== Invalid read of size 4
==2441==    at 0x409490: tyn_p4d_encode32 (tyn_coder.c:669)
==2441==    by 0x4045F0: nodes_term32_flush (tyn_indexer.c:132)
==2441==    by 0x407B77: tyn_exsorter_sort (tyn_exsorter.c:131)
==2441==    by 0x406DDE: tyn_build_index (tyn_indexer.c:731)
==2441==    by 0x40384F: main (tyn_indexer.c:943)
==2441==  Address 0x1233c080 is 0 bytes after a block of size 1,048,576 alloc'd
==2441==    at 0x4A074CD: malloc (vg_replace_malloc.c:236)
==2441==    by 0x406BEB: tyn_build_index (tyn_indexer.c:663)
==2441==    by 0x40384F: main (tyn_indexer.c:943)
==2441==
==2441== Invalid read of size 4
==2441==    at 0x4094A7: tyn_p4d_encode32 (tyn_coder.c:667)
==2441==    by 0x4045F0: nodes_term32_flush (tyn_indexer.c:132)
==2441==    by 0x407B77: tyn_exsorter_sort (tyn_exsorter.c:131)
==2441==    by 0x406DDE: tyn_build_index (tyn_indexer.c:731)
==2441==    by 0x40384F: main (tyn_indexer.c:943)
==2441==  Address 0x1233c088 is 8 bytes after a block of size 1,048,576 alloc'd
==2441==    at 0x4A074CD: malloc (vg_replace_malloc.c:236)
==2441==    by 0x406BEB: tyn_build_index (tyn_indexer.c:663)
==2441==    by 0x40384F: main (tyn_indexer.c:943)
==2441==
==2441== Invalid read of size 4
==2441==    at 0x409574: tyn_p4d_encode32 (tyn_coder.c:694)
==2441==    by 0x4045F0: nodes_term32_flush (tyn_indexer.c:132)
==2441==    by 0x407B77: tyn_exsorter_sort (tyn_exsorter.c:131)
==2441==    by 0x406DDE: tyn_build_index (tyn_indexer.c:731)
==2441==    by 0x40384F: main (tyn_indexer.c:943)
==2441==  Address 0x1233c080 is 0 bytes after a block of size 1,048,576 alloc'd
==2441==    at 0x4A074CD: malloc (vg_replace_malloc.c:236)
==2441==    by 0x406BEB: tyn_build_index (tyn_indexer.c:663)
==2441==    by 0x40384F: main (tyn_indexer.c:943)
==2441==
==2441== Invalid read of size 4
==2441==    at 0x4095A6: tyn_p4d_encode32 (tyn_coder.c:708)
==2441==    by 0x4045F0: nodes_term32_flush (tyn_indexer.c:132)
==2441==    by 0x407B77: tyn_exsorter_sort (tyn_exsorter.c:131)
==2441==    by 0x406DDE: tyn_build_index (tyn_indexer.c:731)
==2441==    by 0x40384F: main (tyn_indexer.c:943)
==2441==  Address 0x1233c088 is 8 bytes after a block of size 1,048,576 alloc'd
==2441==    at 0x4A074CD: malloc (vg_replace_malloc.c:236)
==2441==    by 0x406BEB: tyn_build_index (tyn_indexer.c:663)
==2441==    by 0x40384F: main (tyn_indexer.c:943)
==2441==
==2441== Invalid read of size 4
==2441==    at 0x409524: tyn_p4d_encode32 (tyn_coder.c:697)
==2441==    by 0x4045F0: nodes_term32_flush (tyn_indexer.c:132)
==2441==    by 0x407B77: tyn_exsorter_sort (tyn_exsorter.c:131)
==2441==    by 0x406DDE: tyn_build_index (tyn_indexer.c:731)
==2441==    by 0x40384F: main (tyn_indexer.c:943)
==2441==  Address 0x1233c08c is 12 bytes after a block of size 1,048,576 alloc'd
==2441==    at 0x4A074CD: malloc (vg_replace_malloc.c:236)
==2441==    by 0x406BEB: tyn_build_index (tyn_indexer.c:663)
==2441==    by 0x40384F: main (tyn_indexer.c:943)
==2441==
==2441== Invalid read of size 4
==2441==    at 0x40953A: tyn_p4d_encode32 (tyn_coder.c:700)
==2441==    by 0x4045F0: nodes_term32_flush (tyn_indexer.c:132)
==2441==    by 0x407B77: tyn_exsorter_sort (tyn_exsorter.c:131)
==2441==    by 0x406DDE: tyn_build_index (tyn_indexer.c:731)
==2441==    by 0x40384F: main (tyn_indexer.c:943)
==2441==  Address 0x1233c08c is 12 bytes after a block of size 1,048,576 alloc'd
==2441==    at 0x4A074CD: malloc (vg_replace_malloc.c:236)
==2441==    by 0x406BEB: tyn_build_index (tyn_indexer.c:663)
==2441==    by 0x40384F: main (tyn_indexer.c:943)
==2441==
==2441== Invalid read of size 4
==2441==    at 0x409552: tyn_p4d_encode32 (tyn_coder.c:702)
==2441==    by 0x4045F0: nodes_term32_flush (tyn_indexer.c:132)
==2441==    by 0x407B77: tyn_exsorter_sort (tyn_exsorter.c:131)
==2441==    by 0x406DDE: tyn_build_index (tyn_indexer.c:731)
==2441==    by 0x40384F: main (tyn_indexer.c:943)
==2441==  Address 0x1243c2fc is 12 bytes after a block of size 16 alloc'd
==2441==    at 0x4A074CD: malloc (vg_replace_malloc.c:236)
==2441==    by 0x40785B: tyn_exsorter_sort (tyn_exsorter.c:106)
==2441==    by 0x406DDE: tyn_build_index (tyn_indexer.c:731)
==2441==    by 0x40384F: main (tyn_indexer.c:943)
==2441==
==2441== Invalid read of size 4
==2441==    at 0x407CB7: tyn_iS16_encode32 (tyn_coder.c:96)
==2441==    by 0x409621: tyn_p4d_encode32 (tyn_coder.c:725)
==2441==    by 0x4045F0: nodes_term32_flush (tyn_indexer.c:132)
==2441==    by 0x407B77: tyn_exsorter_sort (tyn_exsorter.c:131)
==2441==    by 0x406DDE: tyn_build_index (tyn_indexer.c:731)
==2441==    by 0x40384F: main (tyn_indexer.c:943)
==2441==  Address 0x1243d880 is 0 bytes after a block of size 16 alloc'd
==2441==    at 0x4A074CD: malloc (vg_replace_malloc.c:236)
==2441==    by 0x40785B: tyn_exsorter_sort (tyn_exsorter.c:106)
==2441==    by 0x406DDE: tyn_build_index (tyn_indexer.c:731)
==2441==    by 0x40384F: main (tyn_indexer.c:943)
==2441==
==2441== Invalid read of size 4
==2441==    at 0x407D20: tyn_iS16_encode32 (tyn_coder.c:109)
==2441==    by 0x409621: tyn_p4d_encode32 (tyn_coder.c:725)
==2441==    by 0x4045F0: nodes_term32_flush (tyn_indexer.c:132)
==2441==    by 0x407B77: tyn_exsorter_sort (tyn_exsorter.c:131)
==2441==    by 0x406DDE: tyn_build_index (tyn_indexer.c:731)
==2441==    by 0x40384F: main (tyn_indexer.c:943)
==2441==  Address 0x1243d880 is 0 bytes after a block of size 16 alloc'd
==2441==    at 0x4A074CD: malloc (vg_replace_malloc.c:236)
==2441==    by 0x40785B: tyn_exsorter_sort (tyn_exsorter.c:106)
==2441==    by 0x406DDE: tyn_build_index (tyn_indexer.c:731)
==2441==    by 0x40384F: main (tyn_indexer.c:943)
==2441==
==2441== Invalid read of size 4
==2441==    at 0x407D37: tyn_iS16_encode32 (tyn_coder.c:108)
==2441==    by 0x409621: tyn_p4d_encode32 (tyn_coder.c:725)
==2441==    by 0x4045F0: nodes_term32_flush (tyn_indexer.c:132)
==2441==    by 0x407B77: tyn_exsorter_sort (tyn_exsorter.c:131)
==2441==    by 0x406DDE: tyn_build_index (tyn_indexer.c:731)
==2441==    by 0x40384F: main (tyn_indexer.c:943)
==2441==  Address 0x1243d8a8 is not stack'd, malloc'd or (recently) free'd
==2441==

==2441== Use of uninitialised value of size 8
==2441==    at 0x3AE9C4726B: _itoa_word (in /lib64/libc-2.14.90.so)
==2441==    by 0x3AE9C49852: vfprintf (in /lib64/libc-2.14.90.so)
==2441==    by 0x3AE9C51FE8: printf (in /lib64/libc-2.14.90.so)
==2441==    by 0x4071EF: tyn_build_index (tyn_indexer.c:888)
==2441==    by 0x40384F: main (tyn_indexer.c:943)
==2441==
==2441== Conditional jump or move depends on uninitialised value(s)
==2441==    at 0x3AE9C47275: _itoa_word (in /lib64/libc-2.14.90.so)
==2441==    by 0x3AE9C49852: vfprintf (in /lib64/libc-2.14.90.so)
==2441==    by 0x3AE9C51FE8: printf (in /lib64/libc-2.14.90.so)
==2441==    by 0x4071EF: tyn_build_index (tyn_indexer.c:888)
==2441==    by 0x40384F: main (tyn_indexer.c:943)
==2441==
document id: 0
==2441== Conditional jump or move depends on uninitialised value(s)
==2441==    at 0x3AE9C4774E: vfprintf (in /lib64/libc-2.14.90.so)
==2441==    by 0x3AE9C51FE8: printf (in /lib64/libc-2.14.90.so)
==2441==    by 0x4073AD: tyn_build_index (tyn_indexer.c:900)
==2441==    by 0x40384F: main (tyn_indexer.c:943)
==2441==
==2441== Use of uninitialised value of size 8
==2441==    at 0x3AE9C4726B: _itoa_word (in /lib64/libc-2.14.90.so)
==2441==    by 0x3AE9C49852: vfprintf (in /lib64/libc-2.14.90.so)
==2441==    by 0x3AE9C51FE8: printf (in /lib64/libc-2.14.90.so)
==2441==    by 0x4073AD: tyn_build_index (tyn_indexer.c:900)
==2441==    by 0x40384F: main (tyn_indexer.c:943)
==2441==
==2441== Conditional jump or move depends on uninitialised value(s)
==2441==    at 0x3AE9C47275: _itoa_word (in /lib64/libc-2.14.90.so)
==2441==    by 0x3AE9C49852: vfprintf (in /lib64/libc-2.14.90.so)
==2441==    by 0x3AE9C51FE8: printf (in /lib64/libc-2.14.90.so)
==2441==    by 0x4073AD: tyn_build_index (tyn_indexer.c:900)
==2441==    by 0x40384F: main (tyn_indexer.c:943)
==2441==
int32_t category: 0
bytes_collected: 972467429
196220 bytes/s
tyn_config->indexer->dl_directory: /dragon/tyan
tyn_config->indexer->memory_limit: 10240000
==2441==
==2441== HEAP SUMMARY:
==2441==     in use at exit: 214,695,668 bytes in 399,272 blocks
==2441==   total heap usage: 401,095 allocs, 1,823 frees, 219,225,806 bytes allocated
==2441==
==2441== LEAK SUMMARY:
==2441==    definitely lost: 9,442,580 bytes in 27 blocks
==2441==    indirectly lost: 34,682,771 bytes in 81 blocks
==2441==      possibly lost: 170,557,809 bytes in 399,140 blocks
==2441==    still reachable: 12,508 bytes in 24 blocks
==2441==         suppressed: 0 bytes in 0 blocks
==2441== Rerun with --leak-check=full to see details of leaked memory
==2441==
==2441== For counts of detected and suppressed errors, rerun with: -v
==2441== Use --track-origins=yes to see where uninitialised values come from
==2441== ERROR SUMMARY: 32680 errors from 23 contexts (suppressed: 2 from 2)
2 4

2 ответа:

У вас здесь много выходных данных. Вы должны были бы сжать его больше к областям, которые вас интересуют. Однако я попытаюсь дать несколько общих указаний.

==2441== Invalid write of size 4

Открывает "блок", который сообщает вам подробную информацию о выделенной памяти и обратном пути стека ее выделения и месте ошибки. ==2441== - это PID процесса, который полезен в случаях, когда несколько процессов выполняются параллельно.

Ошибка сайта (комментарии добавлены с помощью #). Обратный след стека всегда в обратном порядке, то есть аварийный сайт (или то, что обычно становится аварийным) находится в верхней части списка, а вызовы, которые привели к нему, перечислены в обратном порядке ниже:

# This points to a function nodes_term32_flush() in file tyn_indexer.c on line 227
==2441==    at 0x404893: nodes_term32_flush (tyn_indexer.c:227)
# the format is the same, at this line tyn_exsorter_sort() calls nodes_term32_flush()
==2441==    by 0x407B77: tyn_exsorter_sort (tyn_exsorter.c:131)
# ... and so on
==2441==    by 0x406DDE: tyn_build_index (tyn_indexer.c:731)
# ... leading up to the process "entry point"
==2441==    by 0x40384F: main (tyn_indexer.c:943)

Блок памяти, который был затронут. Первая строка говорит нам, что был выделен блок ровно одного MiB и что (вместе с выводом выше) вы читали первые 4 байта (вероятно, 32-битное значение) после последнего выделенного байта этого блока. Остальная часть формата соответствует тому, что вы знаете от стека обратного следа выше.

==2441==  Address 0x1233c080 is 0 bytes after a block of size 1,048,576 alloc'd
==2441==    at 0x4A074CD: malloc (vg_replace_malloc.c:236)
==2441==    by 0x406BEB: tyn_build_index (tyn_indexer.c:663)
==2441==    by 0x40384F: main (tyn_indexer.c:943)
Все последующие повторения - по опыту-чаще всего являются следствием первой ошибки. Поэтому всегда начинайте исправлять первую из перечисленных проблем в последовательности сообщенных проблем.

Теперь для другого класса ошибок, который появляется в выходных данных:

==2441== Use of uninitialised value of size 8
# All library functions here ...
==2441==    at 0x3AE9C4726B: _itoa_word (in /lib64/libc-2.14.90.so)
==2441==    by 0x3AE9C49852: vfprintf (in /lib64/libc-2.14.90.so)
==2441==    by 0x3AE9C51FE8: printf (in /lib64/libc-2.14.90.so)
# ... but this one should be yours. Check out this file/line to see what can be the problem with the printf() call
==2441==    by 0x4071EF: tyn_build_index (tyn_indexer.c:888)
==2441==    by 0x40384F: main (tyn_indexer.c:943)

Следующее, вероятно, опять же просто следствие приведенного выше вывода:

==2441== Conditional jump or move depends on uninitialised value(s)
==2441==    at 0x3AE9C47275: _itoa_word (in /lib64/libc-2.14.90.so)
==2441==    by 0x3AE9C49852: vfprintf (in /lib64/libc-2.14.90.so)
==2441==    by 0x3AE9C51FE8: printf (in /lib64/libc-2.14.90.so)
==2441==    by 0x4071EF: tyn_build_index (tyn_indexer.c:888)
==2441==    by 0x40384F: main (tyn_indexer.c:943)

Я настоятельно рекомендую две вещи: читать ручной работы с Valgrind (я знайте, что это звучит покровительственно, но оно того стоит) и используйте его многочисленные варианты. Я создал несколько функций, которые использую на своих машинах разработки:

# vim: set autoindent smartindent tabstop=2 shiftwidth=2 expandtab filetype=sh:

function vgrun
{
  local COMMAND="$1"
  local NAME="$2"
  [[ -n "$COMMAND" ]] || { echo "Syntax: vgrun <command> <name>"; return; }
  [[ -n "$NAME" ]] || { echo "Syntax vgrun <command> <name>"; return; }
  valgrind \
        --leak-check=full --error-limit=no --track-origins=yes \
        --undef-value-errors=yes --log-file=valgrind-${NAME}.log \
        --read-var-info=yes \
        $COMMAND | tee valgrind-${NAME}-output.log 2>&1
}

function vgtrace
{
  local COMMAND="$1"
  local NAME="$2"
  [[ -n "$COMMAND" ]] || { echo "Syntax: vgtrace <command> <name>"; return; }
  [[ -n "$NAME" ]] || { echo "Syntax vgtrace <command> <name>"; return; }
  valgrind \
        --leak-check=full --error-limit=no --track-origins=yes \
        --undef-value-errors=yes --log-file=valgrind-${NAME}.log \
        --read-var-info=yes --trace-children=yes \
        $COMMAND | tee valgrind-${NAME}-output.log 2>&1
}

function vgdbg
{
  [[ -n "$*" ]] || { echo "Syntax: vgrun <command>"; return; }
  valgrind \
        --leak-check=full --error-limit=no --track-origins=yes \
        --undef-value-errors=yes --read-var-info=yes --db-attach=yes \
        "$@"
}

vgrun просто выполняет команду с помощью Valgrind. Обратите внимание, что команда должна быть в кавычках со всеми своими параметрами, чтобы она работала. vgtrace - это всего лишь вариация vgrun, добавляющая --trace-children=yes в командную строку Valgrind. Наиболее полезным, безусловно, является vgdbg, который попросит вас присоединить GDB к запущенной программе и, таким образом, позволит вам интерактивно отладьте проблему под рукой, в том числе должным образом проверяя фреймы стека, значения и т. д. - Если вы говорите GDB, то есть.

Я бы сначала взглянул на ошибки, говорящие о неинициализированных значениях. Я бы тоже посмотрел, что пишет инвалид. Segfaults часто может быть результатом использования неинициализированного значения. Они также могут быть вызваны недопустимыми записями, которые вызывают повреждение кучи. Выход там дает вам номера строк. Начните искать в этих областях. Вывод там также показывает вам несколько утечек памяти. Следуйте совету вывода и запустите его снова с --leak-check=full, чтобы получить более детальный анализ утечка памяти, так что вы можете отследить их и позаботиться о них.