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