Размер массива, объявленный функцией, приводит к повреждению стека, но чистая компиляция?

Это пример кода, который мне удалось извлечь из исходного исходного кода, который компилируется чисто, но вылетает более или менее случайным образом:

#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 и Address Sanitizer мы обнаружили, что:

char arr[p->f()];

виноват в повреждении стека.

Зная, что p создается во время выполнения и что объявление размера массива выполняется во время компиляции с фиксированным значением, как это компилируется без жалоб? Какое значение p-> f () во время компиляции?

Кроме того, почему memset (запись дополнительных 10 байтов «неопределенного» размера массива) работает без ошибки сегментации?

0

Решение

Вот почему вы всегда должны компилировать с включенными предупреждениями. В этом случае соответствующим является:

main.cpp:66:20: warning: ISO C++ forbids variable length array 'arr' [-Wvla]
char arr[p->f()];
^

(Обратите внимание, что есть и другие предупреждения, это только соответствующее). Массивы переменной длины разрешены gcc как расширение, поэтому ваш код скомпилирован. Но если бы вы видели это предупреждение, вероятно, вы бы приняли другое решение. -Wall -Wextra твой друг.

Кроме того, почему memset (запись дополнительных 10 байтов «неопределенного» размера массива) работает без ошибки сегментации?

Неопределенное поведение не определено, оно не обязательно требует ошибки сегментации.

3

Другие решения

Других решений пока нет …