Это пример кода, который мне удалось извлечь из исходного кода, который компилируется, но сбой в более или менее случайным образом:Размер массива, объявленный функцией, приводит к повреждению стека, но чистая компиляция?
#include <iostream>
#include <cstdio>
#include <cstring>
class base
{
public:
base() {}
virtual const char f(void) = 0 ;
};
class d1 : public base
{
static const char s = 15;
public:
d1()
{
}
const char f()
{
return s;
}
};
class d2 : public base
{
static const char n = 25;
public:
d2()
{
}
const char f()
{
return n;
}
};
void method(char* p, size_t len)
{
memset(p, 0, ((len * sizeof(char)) + 10));
}
int main(int argc, char **argv)
{
base *p = NULL;
if(argc == 2)
{
printf("p shall be instance of d2\n");
p = new d2();
}
else
{
printf("p shall be instance of d1\n");
p = new d1();
}
char arr[p->f()];
printf("Size of arr is %d\n", sizeof(arr));
method(arr, p->f());
}
После нескольких сеансов отладки с помощью GDB и Адрес Sanitizer инструменты мы в что
char arr[p->f()];
является виновником повреждения стека.
Зная, что p создается во время выполнения, и объявление размера массива выполняется во время компиляции с фиксированным значением, как это компилируется без жалобы? Каково значение p-> f() во время компиляции?
Кроме того, почему memset (запись дополнительных 10 байтов «неопределенного» размера массива) выполняется без ошибки сегментации?
Вы используете gcc/clang? Это расширение, которое по умолчанию используется для них. – NathanOliver
[Не компилируется чисто.] (Http://coliru.stacked-crooked.com/a/62ef3e46c5ee6a37) Вы говорите о диалекте GnuC++? Если да, сделайте это явным. –
Ваш memset() в funciton метода() перехватывает ваш массив на 10 байтов. Это может привести к повреждению стека. Вы можете получить случайное поведение, вы можете получить сбой. Вероятно, вы также используете компилятор, который поддерживает VLA в C++ (это означает, что ваш массив имеет размер во время выполнения, а не во время компиляции). – nos