2014-01-11 3 views
0

У меня была очень странная проблема в программе на языке C с перестановкой переменных друг на друга. У меня есть переменная logFilePath, которая определяется следующим образом:Указатель строки в C, переписывающий существующий указатель

logFilePath = pathToFile(logDirectory,argv[2]); 

Функция pathToFile реализуется как это.

char *pathToFile(char *directory, char *file) { 
    char *filePath = malloc(sizeof(*directory)+sizeof(*file)+10); 
    int i; 
    for (i = 0; directory[i] != '\0'; i++) { 
    if (directory[i+1] == '\0' && directory[i] != '/') strcat(directory,"/"); 
    } 
    strcat(filePath, directory); 
    strcat(filePath, file); 
    return filePath; 
} 

По какой-то причине logFilePath модифицируется полностью несвязанной функцией. Функция, в которой он изменяется, называется так

line = getIdentifierFromLine(line); 

И реализация.

char *getIdentifierFromLine(char *line) { 
    char *ident = malloc(sizeof(char)*30); 
    int i = 0; 
    printf("%s\n", ident); 
    while (line[i] != ';') { 
    ident[i] = line[i]; 
    i++; 
    } 
    return ident; 
} 

Проблема заключается в том, что logFilePaths часть, кажется, тот же идент, а именно половина после первых 15 символов. Идентификатор инициализируется части после первых 15 символов logFileDirectory и изменения значения каждого символа в идентификаторе изменяет его в logFileDirectory. Что здесь происходит?

+4

'SizeOf (* каталог)' и 'SizeOf (файл *)' означает 'SizeOf (Char)' – BLUEPIXY

+0

I удалось решить проблему, изменив malloc для filePath в pathToFile на 'sizeof (char) * 150'. Я все еще не понимаю, почему я не получил ошибку сегментации? – stmfunk

+0

filePath не является "". change 'strcat (filePath, directory);' to 'strcpy (filePath, directory);' – BLUEPIXY

ответ

4

sizeof не делает проверку длины строки. Это:

char *filePath = malloc(sizeof(*directory)+sizeof(*file)+10); 

неправ. sizeof(*directory) дает размер символа (обычно 1).

Что вы хотите, это:

char *filePath = malloc(strlen(directory)+strlen(directory)+2); 

2 экстра достаточно, один для дополнительного / и один для нулевого завершающего символа.

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

+0

sizeof (* directory) дает размер char не указатель на char, поэтому, вероятно, 1 – Ervadac

+0

@ Ervadac вы правы, я обновил свой ответ. –

+0

Да, sizeof (variable) более запутанным, чем sizeof (type) imo. – Ervadac

0

Стандартный метод ведения журнала (по моему опыту) заключается в использовании потоков stdout или stderr. В C++, чтобы использовать их вам нужно будет включить iostream, и использовать, как показано ниже:

#include <iostream> 

int main(int argc, char* argv[]) 
{ 
    using std::cout; 
    using std::cerr; 
    using std::endl; 

    cout << "Output message" << endl; 
    cerr << "Error message" << endl; 
} 

Это, однако, только достигает печать на этих выходах, которые обычно заканчиваются в терминале. Если вы хотите использовать эти стандартные методы потока (которые вполне читаемы) для вывода в файл, вам нужно как-то перенаправить ваш вывод. Один из способов сделать это - использовать функцию freopen, предоставляемую cstdio. Это означает, что файл открыт и перемещает данный поток в этот файл. См. Здесь документацию. Примером может быть:

#include <iostream> 
#include <cstdio> 

int main(int argc, char* argv[]) 
{ 
    using namespace std; 
    freopen("output.txt", "w", stdout); 
    freopen("error.txt", "w", stderr); 

    cout << "Output message" << endl; 
    cerr << "Error message" << endl; 
} 
+1

Что? ---------- – Duck

+0

OP находится на C, а не на C++. – sqykly

+0

logFilePath не является журналом приложений, это просто имя переменной. Также приложение находится в C не C++. – stmfunk

0

Проблема заключается в вычислении размера, когда вы выделяете место для filePath:

char *filePath = malloc(sizeof(*directory)+sizeof(*file)+10); 

Здесь directory имеет тип char*, так *directory имеет тип char и sizeof(*directory) является 1. То же самое происходит и с sizeof(*file) и выделяется только 12 байт памяти.

Если этого недостаточно места, путь записывается за конец буфера в пространство, которое позже заканчивается на ident в этой другой функции. Затем запись в *indent изменяет ту же память, которая занята в конце filePath.

Вместо sizeof вы должны использовать strlen() для определения длины входных строк:

char *filePath = malloc(strlen(directory)+strlen(file)+10); 
Смежные вопросы