2015-02-13 3 views
3

Я в настоящее время перекодировал malloc() и должен иметь дело с случаем, когда вызывающий объект вычисляет размер буфера, который приводит к отрицательному значению, которое затем передается в malloc()?C - Перекодирование malloc() как определить отрицательный размер, используемый в вызове?

Я знаю, что параметр size_t, так что беззнаковый int я прав?

Таким образом, я хотел проверить размер, который будет передан на мой перекодированный malloc(), но как я могу это сделать?

Потому что, если я передаю отрицательный параметр, он будет изменен на случайное число, например 18446744073709551613. Я просто получаю.

Итак, мой вопрос: как я могу проверить, является ли параметр отрицательным, когда параметр является size_t (без знака int), он будет напрямую преобразован в астрономическое значение, нет?

+3

Это не случайно, '-1' всегда будет [max unsigned value для этого типа] (http://stackoverflow.com/a/22801135/1708801) –

+4

Нет смысла проверять, не имеет ли значение unsigned int отрицательно –

+0

«Как проверить, является ли параметр отрицательным» - его 'size_t'; по определению и неподписанному интегральному типу, поэтому он уже не отрицателен к моменту его получения. – WhozCraig

ответ

2

Как правило, рекомендуется выполнять все вычисления размера, в которых значение вычитается из другого значения с использованием числовых типов, позволяющих проверить отрицательное значение. Хотя прототип для malloc() вызывает значение size_t, которое является значением без знака, вы можете передать знаковое значение, и компилятор выполнит довольно простое преобразование для вас.

Это общее правило, которое я соблюдаю для расчета размера буфера. Если вы используете знакомые переменные для вычисления, легко определить проблему вычисления размера буфера.

Вы пишите в свой вопрос «Потому что, если я передаю отрицательный параметр, он будет изменен на случайное число, например 18446744073709551613. Я просто получаю». и это не так. большое число - это беззнаковое представление отрицательного значения. Это не случайно.

Другой альтернативой является проверка границ значения.Например, вы можете проверить, больше ли значение size_t, чем 0x7ffffff, которое является самым большим 32-битным знаковым значением и действительно большим размером буфера. На компьютерах, на которых я работаю с отрицательным значением, выраженным как unsigned, будет число больше 0x8000000.

+0

Большое спасибо, вы дали мне все ответы! Я понял, что отрицательный параметр будет изменен на наибольшее возможное число. Но потом я спросил: «Как я могу это сравнить»? Но тогда вы просто дали мне идеальный ответ, когда я сравниваю с «0x8000000», действительно, очень спасибо! – nookonee

2
void *malloc(size_t size); 

Как вы можете видеть, аргумент является неподписанным типом, то есть вы не можете передать отрицательное значение.

В любом случае преобразование из целочисленного значения в неподписанный тип определяется как значение, сохраняющее значение по модулю max_value + 1.

+0

Да, я знаю, но, как я сказал другим, я сделал 'malloc (size_t size)', и если мне нравится 'malloc (-2)' и я printf непосредственно в первой строке моего 'malloc()' I я знаю это, но когда я пытаюсь как malloc (-3) и распечатываю то, что передается 'malloc()' это 18446744073709551613 – nookonee

+0

@nookonee: -3 modulo (SIZE_MAX + 1) - большое число, да. Какой у вас там смысл? – Deduplicator

+0

@nookonee и снова, что это * вопрос *? что если ** я ** назвал вашу функцию 'malloc' с' 18446744073709551613' в качестве моего * фактического * запроса размера, а не '-3'? Что/почему вас волнует, произошло ли это из подписанного беззнакового преобразования, которое вы даже не видели *? Все, о чем вы должны заботиться, это то, соответствует ли запрошенный размер. – WhozCraig

2

Поскольку это неподписанный тип данных, значение не может быть отрицательным.

Ваш вопрос больше, если/как вы можете различать огромное значение, передаваемое намеренно, и огромное значение, исходящее из обертывания.

В общем, это невозможно.

+0

За исключением, по сравнению с текущими 64-разрядными машинами, ни один здравомыслящий разработчик намеренно «malloc» 1e18 байт (т. Е. Один миллиард гигабайт), потому что все знают, что такой огромной машины не существует сегодня. –

+1

@BasileStarynkevitch: Как забавно, многие (номинально нормальные) пользователи C++ делают это ежедневно: clang обязательно передаст огромное значение распределителю, когда вычисляется размер для 'new T [n]' переполнения. И поскольку это нормально делегирует 'malloc' ... – Deduplicator

+0

@BasileStarynkevitch: А что, если кто-то пытается malloc -1e18 байт? Внезапно число выглядело бы разумно. –

1

Да, вы правы. Значение
size_t всегда положительно, даже если вы передадите отрицательное значение в случае функции malloc. Если вообще, если вы передаете отрицательное значение, это отрицательное значение преобразуется в значение без знака типа size_t, что приводит к большому положительному целому числу.

Пример:

int *p = (int*)malloc(-5);
эквивалентно:

int*p = malloc(SIZE_MAX - 1); // SIZE_MAX это максимум size_t ..!

+0

О, ладно, спасибо! Так что, если я хочу попробовать, я должен сравнить размер с параметром с наибольшим size_t возможным? Я прав ? Но я попробовал это, и это невозможно, я попытался сравнить свой параметр с ним. Но gcc говорит: src/malloc.c: 21: 15: error: целочисленная константа настолько велика, что она неподписанна [-Werror] if (size> = 18446744073709551613) ^ src/malloc.c: 21: 3 : error: эта десятичная константа неподписанна только в ISO C90 [-Werror] if (size> = 18446744073709551613) ^ Я что-то не так? – nookonee

+1

Простите меня, но с каких пор 'malloc()' принимает 2 аргумента? :-) –

+0

'malloc()' не имеет двух аргументов. И ваш ответ выглядит очень похоже на этот: http://stackoverflow.com/a/17925794/1187415. –

Смежные вопросы