Выделение недостаточной памяти
Выделение недостаточной памяти.[1]
Эта проверка проверяет на наличие следующих проблем:
Неправильный размер выделенного объекта для приведения.
Доступ к указателям вне границ.
Неправильный тип, используемый в sizeof.
Возможное неправильное использование sizeof.
Неправильный размер выделенного объекта для приведения происходит во время преобразования указателя, когда адрес указателя несовпадает. Если указатель преобразуется в другой тип указателя, размер выделенной памяти должен быть кратен размеру целевого указателя.
Удаление несовпадающего указателя имеет неопределенное поведение и может привести к сбою вашей программы.
Предположим, вы преобразуете указатель мыши ptr1
на ptr2
. Если ptr1
указывает на буфер N
байты и ptr2
является
указатель, где type
*sizeof
является (type
)n
bytes, убедитесь, что 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); }
Доступ к указателю вне границ происходит, когда указатель разыменован вне его границ.
Когда указателю назначается адрес, с указателем ассоциируется блок памяти. Вы не можете получить доступ к памяти за пределами этого блока с помощью указателя.
Удаление указателя за его пределы является неопределенным поведением. Можно считать непредсказуемое значение или попытаться получить доступ к расположению, которое не разрешено, и столкнуться с отказом сегментации.
Исправление зависит от первопричины дефекта. Например, вы разобрали указатель внутри цикла, и произошла одна из следующих ситуаций:
Верхняя граница цикла слишком велика.
Вы использовали арифметику указателя для продвижения указателя с неправильным значением шага указателя.
Чтобы исправить проблему, вы должны изменить привязку цикла или значение шага указателя.
Часто детали результата показывают последовательность событий, которые привели к дефекту. Вы можете реализовать исправление на любом событии в последовательности. Если сведения о результате не отображают историю событий, можно отследить их с помощью опций правого щелчка в исходном коде и просмотреть предыдущие связанные события. Смотрите также Результаты интерпретации Bug Finder в интерфейсе пользователя Polyspace Desktop.
См. примеры исправлений ниже.
Если вы не хотите устранять проблему, добавьте комментарии к своему результату или коду, чтобы избежать другой проверки. Смотрите Адрес Результаты 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
из пяти указателей char. Однако 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
оператор для имени параметра массива, ожидающий размера массива. Однако имя параметра массива само по себе является указателем. The 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; } }
Решимость: Undecidable |
[1] Выдержки из стандарта «Техническая спецификация ISO/IEC TS 17961 - 2013-11-15» воспроизводятся с согласия АФНОР. Только оригинальный и полный текст стандарта, опубликованный AFNOR Editions - доступный через веб-сайт www.boutique.afnor.org - имеет нормативное значение.
1. Если смысл перевода понятен, то лучше оставьте как есть и не придирайтесь к словам, синонимам и тому подобному. О вкусах не спорим.
2. Не дополняйте перевод комментариями “от себя”. В исправлении не должно появляться дополнительных смыслов и комментариев, отсутствующих в оригинале. Такие правки не получится интегрировать в алгоритме автоматического перевода.
3. Сохраняйте структуру оригинального текста - например, не разбивайте одно предложение на два.
4. Не имеет смысла однотипное исправление перевода какого-то термина во всех предложениях. Исправляйте только в одном месте. Когда Вашу правку одобрят, это исправление будет алгоритмически распространено и на другие части документации.
5. По иным вопросам, например если надо исправить заблокированное для перевода слово, обратитесь к редакторам через форму технической поддержки.