Использование Malloc для выделения размера массива в C - PullRequest
1 голос
/ 08 марта 2011

В программе, которую я пишу, у меня есть массив учетных записей (учетная запись - это структура, которую я создал). Мне нужно, чтобы это было видно всем функциям и потокам в моей программе. Тем не менее, я не буду знать, каким должен быть размер, пока основная функция не выяснит это. поэтому я создал его с: учетная запись * account;

и попытайтесь выделить ему место в основном с помощью этого:

number of accounts = 100 //for example
accounts = (account*)malloc(numberOfAccounts * sizeof (account));

Однако, похоже, размер массива больше, чем нужно. Например, существует accounts[150] и т. Д.

Что-то я делаю не так? Как я могу получить размер учетных записей, чтобы быть точно 100? Спасибо

Ответы [ 6 ]

5 голосов
/ 08 марта 2011

Вы не можете этого сделать - malloc() не дает никаких гарантий относительно того, сколько памяти он фактически выделяет (за исключением того, что в случае успеха он вернет указатель на по крайней мере столько же, сколько просил). Если вы обращаетесь к чему-либо за пределами запрошенного вами диапазона, это вызывает неопределенное поведение. Это значит, что это может сработать, но с этим ничего не поделаешь.

Кстати, в C вам не нужно вводить возвращаемое значение из malloc().

4 голосов
/ 08 марта 2011

Даже если это выглядит так, accounts[150] на самом деле не существует.

Так почему же ваша программа продолжает работать?Ну, это потому, что, хотя accounts[150] не является реальным элементом, он лежит в области памяти, к которой ваша программа имеет доступ.

C не содержит проверки индексов во время выполнения - он просто вычисляет соответствующий адрес идоступ к этому.Если ваша программа не имеет доступа к этому адресу памяти, она завершится с ошибкой сегментации (или, в терминах Windows, с нарушением доступа).Если, с другой стороны, программе разрешено иметь доступ к этому адресу памяти, то она просто будет обрабатывать все, что находится по этому адресу, как account.

Если вы попытаетесьизмените это, может произойти почти все - в зависимости от широкого спектра факторов, это может изменить некоторые другие переменные в вашей программе, или, учитывая некоторые очень неудачные обстоятельства, это может даже изменить сам программный код, что может привести ко всемповедение (в том числе аварии).Даже возможно, что никаких побочных эффектов не наблюдалось бы, если бы malloc (по какой-либо причине) выделил больше памяти, чем вы явно просили (что возможно).

Если вы хотите убедиться, что такие ошибки обнаруживаются приво время выполнения вам нужно будет выполнить собственную проверку и обработку ошибок.

1 голос
/ 08 марта 2011

Я не могу найти ничего плохого в том, что вы предоставляете. Если у вас есть структура, например ::100100

struct account{
  int a,b,c,d;
  float e,f,g,h;
}

Тогда вы действительно можете создать массив учетных записей, используя: struct account *accounts = (struct account *) malloc(numAccounts * sizeof(account)); Обратите внимание, что для C приведение void* (тип повторной установки malloc) не необходимо. Он будет активирован автоматически.

[править] Ааа! Теперь я вижу твою проблему! Правильно. Да, вы все равно можете получить доступ к учетным записям [150], но в основном получается, что accounts будет указывать на некоторую область памяти. accounts[150] просто указывает в 150 раз больше размера структуры. Вы можете получить тот же результат, выполнив это: *(accounts + 150), что в основном гласит: «Дайте мне значение в учетных записях местоположения + 150».

Эта память просто не зарезервирована и поэтому вызывает неопределенное поведение. Это в основном сводится к: не делай этого!

0 голосов
/ 08 марта 2011

То, что он работает, не означает, что он существует как часть выделенной вами памяти, скорее всего, он принадлежит кому-то другому.

C не заботится или не знает, что ваша учетная запись * получена от malloc,все, что он знает, это то, что это указатель памяти на что-то, что есть sizeof (account).

accounts [150] обращается к 150-му объекту размера учетной записи из значения в указателе, которое может быть случайными данными, может бытьчто-то еще, в зависимости от вашей системы, это может быть даже ваша программа.

Причина, по которой вещи "работают", заключается в том, что все, что там происходит, неважно, но это не всегда так.

0 голосов
/ 08 марта 2011

Размер учетных записей является точным для 100 структур из указателя результата malloc, если этот адрес не равен нулю.

0 голосов
/ 08 марта 2011

Ваш код в порядке. Когда вы говорите, что аккаунты [150] выходят, вы имеете в виду выход или существует?

Если ваш код дает сбой при доступе к учетным записям [150] (при условии, что numberOfAccounts = 100), то следует ожидать, что вы обращаетесь к памяти вне выделенного вами пространства.

Если вы имели в виду, что существует, то на самом деле это не так, вы просто уходите от конца массива, и возвращаемый указатель указывает на область памяти, отличную от выделенной.

...