Выделение недостаточного объема памяти
Недостаточно памяти. [1 ]
Эта проверка проверяет наличие следующих проблем:
Неверный размер выделенного объекта для приведения.
Доступ указателя выходит за границы.
Неверный тип, используемый в sizeof.
Возможное неправильное использование sizeof.
Неправильный размер выделенного объекта для приведения возникает во время преобразования указателя, когда адрес указателя не выровнен. Если указатель преобразуется в другой тип указателя, размер выделенной памяти должен быть кратен размеру указателя назначения.
Переопределение смещенного указателя имеет неопределенное поведение и может привести к аварийному завершению программы.
Предположим, что вы преобразуете указатель ptr1 кому ptr2. Если ptr1 указывает на буфер N байтов и ptr2 является указатель, где type *sizeof( является type)n байт, убедитесь, что N является целым числом, кратным n.
См. примеры исправлений ниже.
Если вы не хотите устранять проблему, добавьте комментарии к результату или коду, чтобы избежать другой проверки. См. раздел Результаты анализа пространства адресов с помощью исправлений ошибок или обоснований.
#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 Desktop.
См. примеры исправлений ниже.
Если вы не хотите устранять проблему, добавьте комментарии к результату или коду, чтобы избежать другой проверки. См. раздел Результаты анализа пространства адресов с помощью исправлений ошибок или обоснований.
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 для выделения буфера, размер буфера меньше требуемого. Недостаток буфера может привести к возникновению таких недостатков, как переполнение буфера.
Если используется возвращаемое значение 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 Technical Specification - 2013-11-15» воспроизводятся с согласия AFNOR. Нормативную ценность имеет только оригинальный и полный текст стандарта, опубликованный изданиями AFNOR - доступный через веб-сайт www.boutique.afnor.org.
1. Если смысл перевода понятен, то лучше оставьте как есть и не придирайтесь к словам, синонимам и тому подобному. О вкусах не спорим.
2. Не дополняйте перевод комментариями “от себя”. В исправлении не должно появляться дополнительных смыслов и комментариев, отсутствующих в оригинале. Такие правки не получится интегрировать в алгоритме автоматического перевода.
3. Сохраняйте структуру оригинального текста - например, не разбивайте одно предложение на два.
4. Не имеет смысла однотипное исправление перевода какого-то термина во всех предложениях. Исправляйте только в одном месте. Когда Вашу правку одобрят, это исправление будет алгоритмически распространено и на другие части документации.
5. По иным вопросам, например если надо исправить заблокированное для перевода слово, обратитесь к редакторам через форму технической поддержки.