Выделение недостаточно памяти
Неправильно выделенный размер объекта для броска происходит во время преобразования указателя, когда адрес указателя неправильно выравнивается. Если указатель преобразован в различный тип указателя, размер выделенной памяти должен быть кратным размеру целевого указателя.
Разыменование неправильно выровненного указателя имеет неопределенное поведение и может заставить вашу программу отказывать.
Предположим, что вы преобразуете указатель ptr1
к ptr2
. Если ptr1
точки к буферу N
байты и ptr2
указатель, где type
*sizeof (
type
)n
байты, убедитесь тот N
целочисленное кратное n
.
Смотрите примеры мер ниже.
Если вы не хотите устранять проблему, добавьте комментарии в свой результат или код, чтобы избежать другого анализа. Смотрите Результаты Polyspace Адреса Через Исправления ошибок или Выравнивания.
#include <stdlib.h>
void dyn_non_align(void){
void *ptr = malloc(13);
long *dest;
dest = (long*)ptr; //defect
}
В этом примере программное обеспечение повышает дефект на преобразовании ptr
к long*
. Динамически выделенная память о ptr
, 13 байтов, не кратное размеру dest
, 4 байта. Это неточное совмещение вызывает Неправильный выделенный размер объекта для дефекта броска.
Одна возможная коррекция должна использовать размер указателя, который является кратным целевому размеру. В этом примере разрешите дефект путем изменения выделенной памяти 12 вместо 13.
#include <stdlib.h> void dyn_non_align(void){ void *ptr = malloc(12); long *dest; dest = (long*)ptr; }
void static_non_align(void){
char arr[13], *ptr;
int *dest;
ptr = &arr[0];
dest = (int*)ptr; //defect
}
В этом примере программное обеспечение повышает дефект на преобразовании ptr
к int*
в линии 6. ptr
имеет емкость памяти 13 байтов потому что массив arr
имеет размер 13 байтов. Размер dest
4 байта, который не является кратным 13. Это неточное совмещение вызывает Неправильный выделенный размер объекта для дефекта броска.
Одна возможная коррекция должна использовать размер указателя, который является кратным целевому размеру. В этом примере разрешите дефект путем изменения размера массива arr
к кратному 4.
void static_non_align(void){ char arr[12], *ptr; int *dest; ptr = &arr[0]; dest = (int*)ptr; }
#include <stdlib.h>
void *my_alloc(int size) {
void *ptr_func = malloc(size);
if(ptr_func == NULL) exit(-1);
return ptr_func;
}
void fun_non_align(void){
int *dest1;
char *dest2;
dest1 = (int*)my_alloc(13); //defect
dest2 = (char*)my_alloc(13); //not a defect
}
В этом примере программное обеспечение повышает дефект на преобразовании указателя, возвращенного my_alloc(13)
к int*
в линии 11. my_alloc(13)
возвращает указатель с динамически выделенным размером 13 байтов. Размер dest1
4 байта, который не является делителем 13. Это неточное совмещение вызывает Неправильный выделенный размер объекта для дефекта броска. В линии 12, тот же вызов функции, my_alloc(13)
, не вызывает дефект для преобразования в dest2
потому что размер char*
, 1 байт, делитель 13.
Одна возможная коррекция должна использовать размер указателя, который является кратным целевому размеру. В этом примере разрешите дефект путем изменения аргумента для my_alloc
к кратному 4.
#include <stdlib.h> void *my_alloc(int size) { void *ptr_func = malloc(size); if(ptr_func == NULL) exit(-1); return ptr_func; } void fun_non_align(void){ int *dest1; char *dest2; dest1 = (int*)my_alloc(12); dest2 = (char*)my_alloc(13); }
Доступ к указателю за пределы происходит, когда указатель разыменовывается вне его границ.
Когда указатель присвоен адрес, блок памяти сопоставлен с указателем. Вы не можете получить доступ к памяти, кроме того блокируют использование указателя.
Разыменование указателя вне его границ является неопределенным поведением. Можно считать непредсказуемое значение или попытку получить доступ к местоположению, которое не позволено, и столкнитесь с отказом сегментации.
Фиксация зависит от первопричины дефекта. Например, вы разыменовали указатель в цикле, и одна из этих ситуаций произошла:
Верхняя граница цикла является слишком большой.
Вы использовали адресную арифметику с указателями, чтобы усовершенствовать указатель с неправильным значением для шага указателя.
Чтобы устранить проблему, необходимо изменить связанный цикл или значение шага указателя.
Часто детали результата показывают последовательность событий, которые привели к дефекту. Можно реализовать закрепление на любом событии в последовательности. Если детали результата не показывают историю события, можно проследить использование, щелкните правой кнопкой по опциям по исходному коду и смотрите предыдущие связанные события. См. также Интерпретируют Результаты Polyspace Bug Finder.
Смотрите примеры мер ниже.
Если вы не хотите устранять проблему, добавьте комментарии в свой результат или код, чтобы избежать другого анализа. Смотрите Результаты Polyspace Адреса Через Исправления ошибок или Выравнивания.
int* Initialize(void)
{
int arr[10];
int *ptr=arr;
for (int i=0; i<=9;i++)
{
ptr++;
*ptr=i;
/* Defect: ptr out of bounds for i=9 */
}
return(arr);
}
ptr
присвоен адрес arr
это указывает на блок памяти размера 10*sizeof(int)
. В for
- цикл, ptr
постепенно увеличивается 10 раз. В последней итерации цикла, ptr
точки вне блока памяти, присвоенного ему. Поэтому это не может быть разыменовано.
Одна возможная коррекция должна инвертировать порядок шага и разыменовать ptr
.
int* Initialize(void) { int arr[10]; int *ptr=arr; for (int i=0; i<=9;i++) { /* Fix: Dereference pointer before increment */ *ptr=i; ptr++; } return(arr); }
После последнего шага, даже при том, что ptr
точки вне блока памяти, присвоенного ему, это не разыменовывается больше.
Неправильно введите используемый в sizeof, происходит, когда оба из следующих условий содержат:
Вы присваиваете адрес блока памяти указателю или передаете данные между двумя блоками памяти. Присвоение или копия используют sizeof
оператор.
Например, вы инициализируете указатель с помощью malloc (sizeof (
или скопируйте данные между двумя адресами с помощью type
))memcpy (
.destination_ptr
, source_ptr
, sizeof (type
))
Вы используете неправильный тип в качестве аргумента sizeof
оператор. Вы используете тип указателя вместо типа, на который указывает указатель.
Например, чтобы инициализировать
указатель, вы используете type
*malloc (sizeof (
вместо type
*))malloc (sizeof (
.type
))
Независимо от какой type
обозначает, выражение sizeof (
всегда возвращает фиксированный размер. Возвращенный размер является размером указателя на вашей платформе в байтах. Внешний вид type
*)sizeof (
часто указывает на непреднамеренное использование. Ошибка может вызвать выделение блока памяти, который намного меньше, чем, в чем вы нуждаетесь и приводите к слабым местам, таким как переполнение буфера.type*
)
Например, примите тот structType
структура с десятью int
переменные. Если вы инициализируете structType*
указатель с помощью malloc(sizeof(structType*))
на 32-битной платформе указатель присвоен блок памяти четырех байтов. Однако быть выделенным полностью для одного structType
переменная, structType*
указатель должен указать на блок памяти sizeof(structType) = 10 * sizeof(int)
байты. Необходимый размер очень больше фактического выделенного размера четырех байтов.
Инициализировать
указатель, замена type
*sizeof (
в выражении инициализации указателя с type
*)sizeof (
.type
)
sizeof
#include <stdlib.h>
void test_case_1(void) {
char* str;
str = (char*)malloc(sizeof(char*) * 5);
free(str);
}
В этом примере память выделяется для символьного указателя str
использование malloc
из пяти символьных указателей. Однако str
указатель на символ, не указатель на символьный указатель. Поэтому sizeof
аргумент, char*
, является неправильным.
sizeof
АргументОдна возможная коррекция должна совпадать с аргументом к типу указателя. В этом примере, str
символьный указатель, поэтому аргумент должен также быть символом.
#include <stdlib.h> void test_case_1(void) { char* str; str = (char*)malloc(sizeof(char) * 5); free(str); }
Возможное неправильное употребление sizeof происходит, когда Polyspace® Bug Finder™ обнаруживает возможно непреднамеренные результаты использования sizeof
оператор. Например:
Вы используете sizeof
оператор на имени параметра массива, ожидая размер массивов. Однако имя параметра массива отдельно является указателем. sizeof
оператор возвращает размер того указателя.
Вы используете sizeof
оператор на элементе массива, ожидая размер массивов. Однако оператор возвращает размер элемента массива.
Аргумент размера определенных функций, таких как strncmp
или wcsncpy
является неправильным, потому что вы использовали sizeof
оператор ранее с возможно неправильными ожиданиями. Например:
В вызове функции strncmp(string1, string2, num)
, num
получен из неправильного использования sizeof
оператор на указателе.
В вызове функции wcsncpy(destination, source, num)
, num
не количество широких символов, но размера в байтах, полученных при помощи sizeof
оператор. Например, вы используете wcsncpy(destination, source, sizeof(destination) - 1)
вместо wcsncpy(destination, source, (sizeof(desintation)/sizeof(wchar_t)) - 1)
.
Неправильное использование sizeof
оператор может вызвать следующие проблемы:
Если вы ожидаете sizeof
оператор к размеру возвращаемого массива и используют возвращаемое значение, чтобы ограничить цикл, количество запусков цикла меньше, чем, что вы ожидаете.
Если вы используете возвращаемое значение sizeof
оператор, чтобы выделить буфер, buffer size меньше, чем, чего вы требуете. Недостаточный буфер может привести к результирующим слабым местам, таким как переполнение буфера.
Если вы используете возвращаемое значение sizeof
оператор неправильно в вызове функции, функция не ведет себя, как вы ожидаете.
Возможные меры:
Не используйте sizeof
оператор на имени параметра массива или элементе массива, чтобы определить размер массивов.
Лучшая практика состоит в том, чтобы передать размер массивов как параметр отдельной функции и использовать тот параметр в теле функции.
Используйте sizeof
оператор тщательно, чтобы определить аргумент номера функций, таких как strncmp
или wcsncpy
. Например, для широких строковых функций, таких как wcsncpy
, используйте количество широких символов в качестве аргумента вместо количества байтов.
sizeof
Используемый неправильно, чтобы определить размер массивов#define MAX_SIZE 1024
void func(int a[MAX_SIZE]) {
int i;
for (i = 0; i < sizeof(a)/sizeof(int); i++) {
a[i] = i + 1;
}
}
В этом примере, sizeof(a)
возвращает размер указателя a
а не размер массивов.
Одна возможная коррекция должна использовать, другой означает определять размер массивов.
#define MAX_SIZE 1024 void func(int a[MAX_SIZE]) { int i; for (i = 0; i < MAX_SIZE; i++) { a[i] = i + 1; } }
Разрешимость: неразрешимый |
[1] Выписки из стандарта "Техническая характеристика ISO/IEC TS 17961 - 2013-11-15" воспроизводятся с соглашением о AFNOR. Только исходный и полный текст стандарта, как опубликовано Выпусками AFNOR - доступный через веб-сайт www.boutique.afnor.org - имеет нормативное значение.
1. Если смысл перевода понятен, то лучше оставьте как есть и не придирайтесь к словам, синонимам и тому подобному. О вкусах не спорим.
2. Не дополняйте перевод комментариями “от себя”. В исправлении не должно появляться дополнительных смыслов и комментариев, отсутствующих в оригинале. Такие правки не получится интегрировать в алгоритме автоматического перевода.
3. Сохраняйте структуру оригинального текста - например, не разбивайте одно предложение на два.
4. Не имеет смысла однотипное исправление перевода какого-то термина во всех предложениях. Исправляйте только в одном месте. Когда Вашу правку одобрят, это исправление будет алгоритмически распространено и на другие части документации.
5. По иным вопросам, например если надо исправить заблокированное для перевода слово, обратитесь к редакторам через форму технической поддержки.