Разыменование пустого указателя как исправить
Перейти к содержимому

Разыменование пустого указателя как исправить

  • автор:

Ошибка С++, Разыменование пустого указателя.

Программа служит для перевода из арабских чисел в римские. Код:

#include
#include
using namespace std;

int main()
int N=1, I=1, X=10, V=5, L=50, C=100, D=500, M=1000;
int colI = 0, colV = 0, colX = 0, colL = 0, colC = 0, colD = 0, colM = 0;
cin >> N;
if (N > 3999) < cout
while ((N /= M) > M) < colM++; >
while ((N /= M)/=D > D) < colD++; >
while (((N /= C)/=D)/=C > C) < colC++; >while ((((N /= C) /= D) /= C )/=L > L) < colL++; >
while (((((N /= C) /= D) /= C) /= L ) /= X > X) < colX++; >
while ((((((N /= C) /= D) /= C) /= L) /= X) /= V > V) < colV++; >
while (((((((N /= C) /= D) /= C) /= L) /= X) /= V) /= I > I)

cout while (colM > 0) < cout ; while (colD > 0) < cout ;while (colC > 0) < cout ; while (colL > 0) < cout ; while (colX > 0) < cout ; while (colV > 0) < cout ; while (colI > 0) < cout ;
return 0;
system(«pause»);

Лучший ответ
string rom[] = < "M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I" >;
int N, dec[] = < 1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1 >;
cin >> N;
while (N > 0) int i = 0;
while (N < dec[i]) i++;
cout N -= dec[i];
>
Источник: https://otvet.mail.ru/answer/1904096593
Остальные ответы

Анализатор немного ошибся — у тебя деление на ноль, а не разыменование нулевого указателя.
Но. Эту программу нельзя исправить. Это полная жесть.
Лучше поищи в интернете, как эта задача решается.

Динамический массив СИ

Дальше я заполняю его через scanf_s(«%s», temp, 49); order[1] = temp; и тд, но в итоге все елементы будут равны последнему значению. На free(order); выдаёт ошибку. Сама студия жалуется на разыменование пустого указателя order в этой строке order[i] = (char*)malloc(osize * sizeof(char)); Где ошибка?

Отслеживать
219k 15 15 золотых знаков 119 119 серебряных знаков 230 230 бронзовых знаков
задан 5 апр 2021 в 21:41
Vlad Ryazantsev Vlad Ryazantsev
3 3 3 бронзовых знака

1 ответ 1

Сортировка: Сброс на вариант по умолчанию

Очень интересное решение. Итак, у вас есть указатель на выделенную память (которую потом можно будет удалить через free ) order[1] .

Вы перезаписываете этот указатель

 order[1] = temp; 

и теперь он (как и все остальные, по окончании работы) указывает на память, выделенную в стеке массиву temp . Еще раз и медленно — все указатели указывают на одну и ту же память в стеке (к которой применять free нельзя). Т.е. все указывают на одну и ту же последнюю строку.

Видимо, вы просто прогуляли лекцию, где рассказывалось, что для копирования строк используются функции наподобие strcpy() .

Еще — вам точно хватит места под вводимые слова? Все же в temp может поместиться 49-символьная строка, а в order[i] — только четырехсимвольная.

И еще — судя по вашим (char*) перед malloc вы все же компилируете в режиме C++, а не С — в С это приведение не требуется.

P.S. VC++ ни о каком разыменовании в указанном вами месте не говорит. Только о том, что после temp[50] вы точку с запятой забыли.

Разыменование пустого указателя как исправить

Указатели поддерживают ряд операций: присваивание, получение адреса указателя, получение значения по указателю, некоторые арифметические операции и операции сравнения.

Присваивание адреса

Указателю можно присвоить адрес объекта того же типа, либо значение другого указателя. Для получения адреса объекта используется операция & :

int a ; int *pa ; // указатель pa хранит адрес переменной a

При этом указатель и переменная должны иметь один и тот же тип, в данном случае это тип int.

Разыменование указателя

Операция разыменования указателя представляет выражение в виде *имя_указателя . Эта операция позволяет получить объект по адресу, который хранится в указателе.

#include int main() < int a ; int *pa ; // хранит адрес переменной a std::cout #include int main() < int a ; int b ; int *pa ; // указатель на переменную a int *pb ; // указатель на переменную b std::cout pa: address=0x56347ffc5c value=10 pb: address=0x56347ffc58 value=2 pa: address=0x56347ffc58 value=2 b value=125

Нулевые указатели

Нулевой указатель (null pointer) - это указатель, который не указывает ни на какой объект. Если мы не хотим, чтобы указатель указывал на какой-то конкретный адрес, то можно присвоить ему условное нулевое значение. Для определения нулевого указателя можно инициализировать указатель нулем или константой nullptr :

int *p1; int *p2<>;

Ссылки на указатели

Так как ссылка не является объектом, то нельзя определить указатель на ссылку, однако можно определить ссылку на указатель. Через подобную ссылку можно изменять значение, на которое указывает указатель или изменять адрес самого указателя:

#include int main() < int a ; int b ; int *p<>; // указатель int *&pRef

; // ссылка на указатель pRef = &a; // через ссылку указателю p присваивается адрес переменной a std::cout &:

int a ; int *pa ; std::cout >, >=, , ,==, !=. Операции сравнения применяются только к указателям одного типа. Для сравнения используются номера адресов:

#include int main() < int a ; int b ; int *pa ; int *pb ; if(pa > pb) std::cout

Консольный вывод в моем случае:

pa (0xa9da5ffdac) is greater than pb (0xa9da5ffda8)

Приведение типов

Иногда требуется присвоить указателю одного типа значение указателя другого типа. В этом случае следует выполнить операцию приведения типов с помощью операции (тип_указателя *) :

#include int main() < char c ; char *pc ; // указатель на символ int *pd <(int *)pc>; // указатель на int void *pv ; // указатель на void std::cout std::cout

Предупреждение C6011

Разыменовывание указателя NULL "pointer-name".

Замечания

Это предупреждение указывает, что код разоменовывает потенциально пустой указатель. Если значение указателя недопустимо, результат становится неопределенным. Чтобы устранить проблему, проверьте указатель перед использованием.

Имя анализа кода: DEREF_NULL_PTR

Пример

Следующий код создает это предупреждение, так как вызов может возвращать malloc значение NULL, если недостаточно памяти доступно:

#include void f( ) < char *p = ( char * ) malloc( 10 ); *p = '\0'; // code . free( p ); >

Чтобы исправить это предупреждение, проверьте указатель на значение NULL, как показано в следующем коде:

#include void f( ) < char *p = ( char * )malloc ( 10 ); if ( p ) < *p = '\0'; // code . free( p ); >> 

Функции могут иметь параметры, аннотированные с помощью Null свойства в условии Pre . Выделите память внутри этих функций перед расшифровки параметра. Следующий код создает предупреждение C6011, так как предпринята попытка разыменовки пустого указателя ( pc ) внутри функции без первого выделения памяти:

#include using namespace vc_attributes; void f([Pre(Null=Yes)] char* pc) < *pc='\0'; // warning C6011 - pc is null // code . >

Небрежное использование malloc и free приводит к утечкам памяти и исключениям. Чтобы свести к минимуму эти утечки и проблемы исключений в целом, избегайте выделения необработанной памяти самостоятельно. Вместо этого используйте механизмы, предоставляемые стандартной библиотекой C++ (STL). Это операторы shared_ptr , unique_ptr , а также vector . Дополнительные сведения см. в разделе "Смарт-указатели " и стандартной библиотеки C++.

Эвристика

Эвристика, используемая для уменьшения числа предупреждений в устаревшем коде, предполагает, что указатель не NULL является нет, если нет доказательств того, что это NULL . В примерах, которые мы видели до сих пор, указатели, возвращаемые malloc или new могут быть NULL вызваны сбоем выделения. Другая характеристика, которую модуль анализа использует в качестве доказательства nullability, заключается в том, что программа явно проверка для NULL . Это показано в следующих примерах:

void f(int* n) < *n = 1; // Does not warn, n is assumed to be non-null >void f(int* n) < if (n) < (*n)++; >*n = 1; // Warns because the earlier conditional shows that n might be null > 

Во втором случае пользователь может исправить предупреждение, переместив *n = 1 строку внутри блока if.

См. также

  • Использование заметок SAL для уменьшения дефектов кода
  • NULL
  • Операторы косвенного обращения и адреса операнда
  • malloc
  • free
  • Оператор new
  • Оператор delete

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *