2015-04-30 3 views
0

У меня есть этот код, где я tokenize строку и поиск значения.понимание указателя, возвращаемого strtok

char string[]="Name=Marcus&greeting=goodmorning"; 
char* Name=parsePostData("Name",string); 




char* parsePostData(char s[],char t[]) 
{ 
    char *pch; 
    char *pp="Marcus"; 

    char tCpy[512];//Make a copy. Otherwise, strtok works on the char pointer, and original char array gets modified/ corrupted. 
    strcpy(tCpy,t); 
    pch = strtok (tCpy,"=&"); 
    while (pch != NULL) 
    { 
     if(strcmp(pch,s)==0) { 
      pch= strtok (NULL, "&"); 
      //Case 1. what I need. but it is causing issues 
      //after I write to flash, and restart the board. 
      return pch; 

      //Case 2. Forced test case. works perfect.    
      //return pp; 


     }else{ 
     pch = strtok (NULL, "=&"); 
     } 
    } 

} 

В чем разница между двумя случаями внутри функции?

+2

'char l []' имеет автоматическую продолжительность хранения. Когда функция возвращается, конец жизни 'l' заканчивается, и любой доступ к ней является неопределенным поведением. Для его строки вам нужно хранить 'malloc()' хранилище, если вы хотите его вернуть. – EOF

+0

Хорошо, спасибо большое! – aVC

+0

@EOF Я обновил вопрос, чтобы показать свою настоящую проблему. Не могли бы вы взглянуть? Я работаю над платой arduino и использую библиотеку dueFlashStorage для записи значений в flash. Но эта функция дает мне проблемы в течение двух дней. – aVC

ответ

1

В чем разница между двумя случаями внутри функции?

Случай 1.

Как несколько человек сказал вам, последовательность

pch = strtok (tCpy,"=&"); 
/* ... */ 
pch= strtok (NULL, "&"); 

результаты в pch быть указатель на локальный массив tCpy (или NULL, если исходная строка не содержат либо '=', либо '&'). Поскольку tCpy является локальным массивом, он выходит за пределы области действия в конце функции, после чего любые указатели на нее перестают быть действительными. На практике память, которую он занимает, вероятно, повторно используется следующей вызываемой функцией.


Случай 2.

Код

char *pp="Marcus"; 

инициализирует pp, чтобы указать на статический, анонимный массив символов, содержимое которого являются завершающим нулем строку "Marcus". Поскольку массив имеет статическую продолжительность хранения, указатель на него остается действительным после выхода функции.


У вас есть три основных варианта работы вокруг этого вопроса:

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

ПРИМЕЧАНИЕ ХОРОШО: любое изменение в функции выделения памяти для возврата к вызывающему дает ответственность вызывающего абонента для освобождая эту память, когда он больше не используется. Для этого требуется указатель на стартовый выделенного блока, а не на какое-то случайное место в середине, поэтому вам нужно будет передать два указателя для выполнения этой работы (один через аргумент).

Когда все будет сказано и сделано, я думаю, вам было бы разумно выбрать вариант варианта 1.Если бы это я, я бы просто позволил функции потреблять переданную ему строку.

UPDATE: Кроме того, в случае 2, программа изображение содержит данные ваши указатели указывают на. Предполагая, что он всегда загружается по тому же адресу, сохранение и восстановление значения указателя вместо того, что, по его мнению, может действительно работать только для этой программы, потому что вы повторно инициализируете отмеченную память, загружая изображение программы поверх нее. То же самое не применяется, если вы скопируете строку в рабочий массив, потому что хотя массив имеет статическую продолжительность, он не инициализируется данными, которые вы хотите восстановить.

+0

John, я попробовал позволить функции потреблять строку. Проблема возникает только при перезагрузке платы и считывании из памяти в первый раз. Я опубликовал комментарий/выпуск на странице библиотеки git. Надеюсь, что это мой код, вызывающий проблему, а не bcz любого ограничения Arduino C. – aVC

+0

Точка библиотеки предназначена для сохранения данных во флеш-память, поэтому даже после перезагрузки/восстановления данных данные могут быть восстановлены. Или вот как я это понял. – aVC

+0

Это ваш код, но главная проблема заключается не в функции 'parsePostData()'. Поскольку @EOF уже объяснил вам, проблема заключается в том, как вы его сохраняете, чтобы мигать. Тот факт, что это, казалось, сработало для вас в случае 2, - красная селедка. Я обновил свой ответ и объяснил, почему этот особый случай может представлять иллюзию работы. –

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