Мусор в указателе

sizz
Offline
Зарегистрирован: 24.08.2015
#include <EEPROM.h>
char *val[1];  ////массив конфигурации
void setup() 
{
  Serial.begin(9600);
  initil();
}

void loop() 
{
delay(500);

}

void initil()
{
rd(1,4,0);/////чтение из eeprom(адрес eeprom,длина,массив)
Serial.println(val[0]);  
}

void rd(int a,int b,int c)/////функция чтения
{
char ms[b]; 
for(int n = 0; n < b; n++){     
ms[n] = EEPROM.read(n+a);     
}
val[с]=ms;
}

При выводе в функции initil в порт выводится мусор, если выводить из функции rd, то всё норм, если вынести массив ms в глобальные переменные то тоже всё работает, почему мусор выводится, понимаю что как то не так с указателями работаю.

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Глобальная переменная инициализируется локальной, которая после выхода из функции является мусором. Локальные переменные хранятся в стеке.

sizz
Offline
Зарегистрирован: 24.08.2015

kisoft пишет:
Глобальная переменная инициализируется локальной, которая после выхода из функции является мусором. Локальные переменные хранятся в стеке.

Спасибо!!! но непонятно немного... разве val[0]=ms; не копирует значения из локальной в глобальную? перед уничтожением локальной. Ведь если обьявить глобальный String или массив Char и делать тоже самое то всё работает...не работает именно с двумерным массивом через указатель

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Это всего лишь копирование указателя, а он в стеке. Никогда не возвращайте из функции указатель на локальную переменную, результат всегда один, мусор

sizz
Offline
Зарегистрирован: 24.08.2015

kisoft пишет:
Это всего лишь копирование указателя, а он в стеке. Никогда не возвращайте из функции указатель на локальную переменную, результат всегда один, мусор

Теперь ясно, а как правильно можно записать тоже самое? Ничего кроме этого в голову не приходит...но как тогда длину узнавать((

#include <EEPROM.h>
char val[1][5];  ////массив конфигурации
void setup() 
{
  Serial.begin(9600);
  initil();
}

void loop() 
{
delay(500);

}

void initil()
{
rd(1,4,0);/////чтение из eeprom(адрес eeprom,длина,массив)

Serial.println(val[0]);      
}

void rd(int a,int b,int c)/////функция чтения
{
char ms[b]; 
for(int n = 0; n < b; n++){     
ms[n] = EEPROM.read(n+a);     
}
strcpy(val[0],ms);
}

 

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

У строки в С массив char как правило завершается символом окончания строки, т.е. символом '\0'.
Потому вместо strcpy можно использовать memcpy и после этого записывать '\0' в конец строки. Например.

sizz
Offline
Зарегистрирован: 24.08.2015

kisoft пишет:
У строки в С массив char как правило завершается символом окончания строки, т.е. символом '\0'. Потому вместо strcpy можно использовать memcpy и после этого записывать '\0' в конец строки. Например.

Спасибо огромное, А как динамически выделить память для двумерного массива(не используя String)? или хотя бы статически но каждому элементу разную?

и еще не понятно, например при обьявлении двух глобальных обьектов String компилятор выдает ошибку линка LD, если в loop поставить любую задержку, то всё нормально..

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

По первому - максимальную длину плюс 1 для '\0'. Переменная длина для статических массивов невозможна без извратов.
По второму - нонсенс, скетч в студию

sizz
Offline
Зарегистрирован: 24.08.2015

kisoft пишет:
По первому - максимальную длину плюс 1 для '\0'. Переменная длина для статических массивов невозможна без извратов. По второму - нонсенс, скетч в студию

String a;
String b;
void setup() {
  // put your setup code here, to run once:

}

void loop() {
  // put your main code here, to run repeatedly:

}

Arduino: 1.6.5 (Windows XP), Плата"Arduino Uno"

collect2.exe: error: ld returned 5 exit status
Ошибка компиляции.

 

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Скорее всего баг линкера, проверить смогу только завтра вечером
UPD: но сразу говорю, не перевариваю String

sizz
Offline
Зарегистрирован: 24.08.2015

kisoft пишет:
Скорее всего баг линкера, проверить смогу только завтра вечером UPD: но сразу говорю, не перевариваю String

Да не только String, тоже самое с любыми массивами если их больше 1го

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

На 1.6.4. без проблем компилируется скетч, скопированный из сообщения #8.

1.6.5. только дома. Хотя, предполагаю, что так же скомпилируется без проблем.

UPD: Прямо сейчас скачал 1.6.5-r2 и скомпилировал. Я был прав. Без проблем.

OS Windows 7 Professional 64

 

Клапауций 998
Offline
Зарегистрирован: 12.08.2015

sizz пишет:

Arduino: 1.6.5 (Windows XP), Плата"Arduino Uno"

collect2.exe: error: ld returned 5 exit status
Ошибка компиляции.

пробуйте Arduino: 1.0.х

sizz
Offline
Зарегистрирован: 24.08.2015

Да, действительно, на Win 7 компилируется.....видимо проблема из за XP

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Так уже была тема здесь, про проблемы с ld на ХРюше на старших версиях, лечили сменой ld или типа того, не читал до конца.