Переполнение массива Valgrind внутри объектов

У меня есть простая программа, как показано ниже.

struct Test
{
    int a[5];
    int b;
};

int main()
{
    Test* t = new Test;
    t->b = 1;
    t->a[5] = 5;          //This is an illegal write
    cout << t->b << endl; //Output is 5
    return 0;
}

Запуск его с Valgrind Memcheck не сообщил о незаконной записи в память.

Я заметил, что Valgrind утверждает, что инструмент Memcheck не может обнаружить глобальное переполнение или переполнение массива стека, но этот массив находится в куче, верно? Просто массив находится в объекте.

Это то, что Valgrind действительно не может обнаружить такую ​​ошибку, или я просто сделал что-то не так? Если первое верно, то есть ли другой инструмент, который может обнаружить этот тип ошибки?

================================================== ========================

Обновить:

Команда компиляции, которую я использовал, была g++ -O0 -g main.cc, valgrind команда была просто valgrind ./a.out, который должен ссылаться на memcheck инструмент по умолчанию.

Версия компилятора gcc version 4.4.7 20120313 (Red Hat 4.4.7-4) (GCC), а также valgrind версия valgrind-3.5.0,

Вывод Valgrind при запуске этой программы:

==7759== Memcheck, a memory error detector
==7759== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==7759== Using Valgrind-3.5.0 and LibVEX; rerun with -h for copyright info
==7759== Command: ./a.out
==7759== 
5
==7759== 
==7759== HEAP SUMMARY:
==7759==     in use at exit: 24 bytes in 1 blocks
==7759==   total heap usage: 1 allocs, 0 frees, 24 bytes allocated
==7759== 
==7759== LEAK SUMMARY:
==7759==    definitely lost: 24 bytes in 1 blocks
==7759==    indirectly lost: 0 bytes in 0 blocks
==7759==      possibly lost: 0 bytes in 0 blocks
==7759==    still reachable: 0 bytes in 0 blocks
==7759==         suppressed: 0 bytes in 0 blocks
==7759== Rerun with --leak-check=full to see details of leaked memory
==7759== 
==7759== For counts of detected and suppressed errors, rerun with: -v
==7759== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 4 from 4)

2 ответа

Решение

Я думаю ниже предложение, которое вы уже нашли:

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

В случае вашего определения класса это следует интерпретировать следующим образом: хотя объект класса размещается динамически, сам массив размещается статически.

Я проверил несколько случаев:

Valgrind сообщит о недопустимой записи, если массив будет динамически размещен:

struct Test
{
    int *a;
    int b;
};

int main()
{
    Test* t = new Test;
    t->a = new int[5];
    t->b = 1;
    t->a[5] = 5;          //This is an illegal write
    cout << t->b << endl; //Output is 5
    delete [] t->a;
    delete t;
    return 0;
}

Также будет сообщено об ошибке, если вы измените порядок членов на:

struct Test
{
  int b;  
  int a[5];
};

Это связано с тем, что при попытке записи в [5] мы будем уже позади динамически размещенного объекта.

С оригинальным определением класса, если вы попытаетесь написать в [6] - потому что тогда мы позади b так за динамически размещаемым объектом.


Обновление: gcc sanitizer (я тоже подозреваю, что clang) обнаруживает это вне связанного доступа во время выполнения, компилируя:

g++ -fno-omit-frame-pointer -fsanitize=bounds m.cpp

Выход:

m.cpp:15:7: runtime error: index 5 out of bounds for type 'int [5]'

У Valgrind, кажется, есть более новый инструмент под названием SGCheck для обнаружения переполнения массива стека.

Кажется, нужна версия больше, чем 3.8

проверить эту ссылку

Он сказал

SGCheck — это инструмент для поиска выхода за пределы стека и глобальных массивов. Он работает с использованием эвристического подхода, основанного на наблюдениях за вероятными формами доступа к стеку и глобальному массиву.

Другие вопросы по тегам