Выделение недостаточно памяти
Неправильно выделенный размер объекта для броска происходит во время преобразования указателя, когда адрес указателя неправильно выравнивается. Если указатель преобразован в различный тип указателя, размер выделенной памяти должен быть кратным размеру целевого указателя.
Разыменование неправильно выровненного указателя имеет неопределенное поведение и может заставить вашу программу отказывать.
Предположим, что вы преобразовываете указатель 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. По иным вопросам, например если надо исправить заблокированное для перевода слово, обратитесь к редакторам через форму технической поддержки.