Будет ли компилятор C автоматически использовать строку const автоматически? [Дубликат]

Не так ясно, что функция всегда должна возвращать объекты ограниченного типа или что возвращение None является неправильным. Например, re.search может возвращать объект _sre.SRE_Match или объект NoneType :

  import re match = re.search (  'a', 'a') type (match) # & lt; type '_sre.SRE_Match' & gt;  match = re.search ('a', 'b') type (match) # & lt; type 'NoneType' & gt;   

Разработанный таким образом, вы можете проверить соответствие с idiom

 , если совпадение: # do xyz  

Если разработчикам потребовался re.search для возврата объекта _sre.SRE_Match , тогда идиома должна была бы измениться на

 , если match.group (1)  None: # do xyz  

Не было бы никакого существенного усиления, требуя, чтобы re.search всегда возвращал объект _sre.SRE_Match .

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

Также обратите внимание, что оба _sre.SRE_Match и NoneType являются экземплярами объекта, поэтому в широком смысле они одного типа. Поэтому правило, что «функции всегда должны возвращать только один тип», совершенно бессмысленно.

Сказав это, есть прекрасная простота для функций, возвращающих объекты, все из которых имеют одни и те же свойства. (Утиная печать, а не статическая типизация, - это путь python!) Это может позволить вам объединить функции: foo (bar (baz))) и с уверенностью знать тип объекта, который вы получите на другом конце.

Это поможет вам проверить правильность кода. Требуя, чтобы функция возвращала только объекты определенного ограниченного типа, проверять меньше случаев. «foo всегда возвращает целое число, поэтому, когда целое число ожидается везде, я использую foo, я золотой ...»

18
задан Niklas R 29 February 2012 в 20:26
поделиться

2 ответа

Строковые литералы хранятся таким образом, что они доступны для жизни программы; если вы пишете

char *ptr = "This is a test";

, все, что записано на ptr, это адрес строкового литерала "This is a test". Даже если переменная ptr выходит за пределы области видимости, строковый литерал продолжает существовать в своем собственном разделе памяти, который не тот же раздел, используемый malloc (по крайней мере, не логический уровень). Обратите внимание, что несколько экземпляров одного и того же строкового литерала могут разрешаться в одном месте; IOW, учитывая

char *p0 = "This is a test";
char *p1 = "This is a test";

p0 и p1, могут содержать один и тот же адрес (это зависит от того, сопоставлено ли несколько вхождений строковых литералов в одно и то же место).

Когда вы вызываете Container_new, все, что вы делаете, копирует адрес в container->buffer и globalBuffer; оба заканчиваются, указывая на то же самое, что существует независимо от любого из них. free -ing container не влияет на строковый литерал, на который указывает container->buffer, поэтому printf(globalBuffer); по-прежнему отображается "Test-string.".

Итак, вы должны not вызывать

free(container->buffer);

для этой конкретной программы, так как вы не назначили результат malloc, calloc или realloc.

Если вы, OTOH, вы написали Container_new как

Container* Container_new(char* buffer) 
{
  Container* container = malloc(sizeof(Container));
  container->buffer    = malloc(strlen(buffer) + 1);  // Allocate memory to 
  if (container->buffer)                              // store a *new* instance
  {                                                   // of the input string. 
    strcpy(container->buffer, buffer);                // This will need to be 
  }                                                   // freed before freeing
  globalBuffer         = buffer;                      // the container
  return container;
}

, то вы хотели бы освободить container->buffer перед освобождением container.

27
ответ дан John Bode 16 August 2018 в 00:19
поделиться
  • 1
    Ничего себе, хороший ответ, очень оценили! – Niklas R 1 March 2012 в 08:17

Вы никогда не будете free() памятью, что вы не malloc() ed.

Способ, которым компилятор реализует строковые литералы, не является вашим бизнесом: это деталь реализации. Вы можете free() указатель на память, который вы выделили с помощью malloc(), и только те, или вы рискуете жизнью своей системы.

В идеале, вызовы malloc() и free() вызовы должны отображаться на одном и том же «уровне проектирования» (внутри одного и того же файла реализации для того же модуля, например), и они должны идеально соответствовать: один free() для каждого malloc(). но это не всегда возможно.

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

27
ответ дан Nate 16 August 2018 в 00:19
поделиться
  • 1
    +1, кроме случаев, когда он находится в strdup(). – Mysticial 29 February 2012 в 20:30
  • 2
    @Mysticial: стандартная библиотека C - очень хороший пример плохого дизайна ... – Adrien Plisson 29 February 2012 в 20:36
  • 3
    Теперь, когда я смотрю, это не похоже, что это часть стандарта. Это в POSIX. – Mysticial 29 February 2012 в 20:38
  • 4
    Если это плохой дизайн для библиотек, чтобы дать вам указатели и сказать вам, чтобы освободить их, когда они вам больше не нужны ... Какой правильный способ обработки освобождения памяти malloc'd от библиотек? – Attila Szeremi 20 September 2013 в 16:59
  • 5
    @ SzerémiAttila: библиотека должна предоставить вам вызов функции для освобождения выделенной памяти. это гарантирует, что правильная функция вызывается для освобождения указателя (в зависимости от используемой среды выполнения и способа связывания библиотеки, malloc() и free() могут быть не такими же внутри или вне библиотеки) – Adrien Plisson 21 September 2013 в 17:04
Другие вопросы по тегам:

Похожие вопросы: