LINUX.ORG.RU

Help. C.


1

2

Доброго времени суток. Изучаю C. Столкнулся с проблемой: если я открываю 2 разных файла при помощи fopen, то при использованиие gets или fgets вылетает

Segmentation fault

Если fopen использован 1, то все хорошо.

Где искать ошибку?

Сильно не бейте.


Ответ на: комментарий от false
#include <stdio.h>

int main(int argc, char *argv[])
{
	FILE *fp;
	FILE *fp2;
	char *s;
	if ((fp = fopen(argv[1], "r")) != NULL) {
		if ((fp2 = fopen(argv[2], "a")) != NULL) {
			gets(s);
			fclose(fp2);
		}
		fclose(fp);
	}
	return 0;
}

momo
() автор топика
Ответ на: комментарий от korvin_

Действительно. тупанул. Спасибо. В таком случае вопрос. Почему когда пишу так, все нормально:

char *s;
s = "qwe";

Почему память выделять тут не нужно?

momo
() автор топика
Последнее исправление: momo (всего исправлений: 1)
Ответ на: комментарий от momo

Потому что, когда ты написал "qwe", компилятор выделил этой строке кусок памяти в бинарнике.

s = "qwe" --- это не чтение строки.

d ★★★★
()
Ответ на: комментарий от korvin_

А как лучше выделять память под нее? Если я создам строку char line[](а потом сделаю s = line) , выделится ли под нее память или надо через sizeof? Сколько тогда выделять?

momo
() автор топика
Ответ на: комментарий от momo
/*Так*/
char* s = (char*)malloc(sizeof(char) * n); /*не забыть сделать free(s) в конце!*/
/*Но лучше, на мой взгляд, так*/
char s[ 128 ]; /*Константу можно выбрать по своему вкусу/применению */
Deleted
()
Последнее исправление: ecko (всего исправлений: 2)
Ответ на: комментарий от momo

Хоть вопрос был и не мне, отвечу.

В си не бывает «как надо» и «как не надо». Возьми K&R, прочитай и пойми, как оно работает. Тогда будет ясно, что можно делать, а что нельзя и почему.

d ★★★★
()
Ответ на: комментарий от d

Если компилятор выделяет память под «qwe», когда эта память освобождается? Только после выполнения программы?

momo
() автор топика
Ответ на: комментарий от korvin_

Потому что она автоматически выделена под литерал «qwe».

Только писать в неё нельзя, потому что это const память.

ТС, используй сразу valgrind.

quasimoto ★★★★
()
Ответ на: комментарий от quasimoto

Только писать в неё нельзя, потому что это const память.

Ну об этом он не спрашивал. =)

korvin_ ★★★★★
()
Ответ на: комментарий от intelfx

Но она же все равно занимается? Или как только я сделаю так, чтобы s указывал на другой адрес в памяти, она освободится?

momo
() автор топика
Ответ на: комментарий от momo

Серьёзно, почитай K&R или Прату (последнее — хороший учебник), систематически, а не прыгая по диагонали. Ты, судя по всему, плохо понимаешь, что такое указатель.

Отвечая на конкретный вопрос — да, память занятая под литерал вида "qwe", остаётся занятой на всём протяжении работы программы. Это секция константных данных; что-то вроде глобальной переменной, только неизменяемой.

intelfx ★★★★★
()
Последнее исправление: intelfx (всего исправлений: 2)
Ответ на: комментарий от intelfx

Я не прыгаю, я последовательно читаю, и что такое указатель понимаю) Просто не знал насчет памяти подобных литералов.

momo
() автор топика
Ответ на: комментарий от Deleted
char s[ 128 ]; /*Константу можно выбрать по своему вкусу/применению */

Почему же она должна быть константой?

char * s = (char[128]){};

А почему не так?

anonymous
()
Ответ на: комментарий от momo

Потому что компилятор наперед знает, что тут 4 символа и выделяет памяти сколько нужно.

LongLiveUbuntu ★★★★★
()
Ответ на: комментарий от anonymous

Почему же она должна быть константой?

Я почему-то думал, что иначе мы отловим ошибку О_о неужто это в крестах, а в сях нет?

А почему не так?

Мой вариант лаконичнее.

Deleted
()
Ответ на: комментарий от Deleted

Не хочу влезать в спор, но эти определения не эквивалентны, ведь так?

char s[ 128 ];
char * s = (char[128]){};

momo
() автор топика
Ответ на: комментарий от Deleted

Но ведь первое массив, второе указатель, разве не так? В первом случае мы не можем сделать s++, а во втором можем(если только это не аргументы функции). И в первом случае мы разве можем написать

s = "qwe"
?

momo
() автор топика
Последнее исправление: momo (всего исправлений: 2)
Ответ на: комментарий от momo

Срочно садись за K&R, у тебя серьёзные проблемы с пониманием того, что такое указатель в принципе.

В самом K&R написано, что если у нас есть char a[128], то a будет указывать на нулевой элемент, (a+1) — на первый,..., (a+127) — на последний(в данном случае).

Соответственно, записи a[4] и *(a+4) будут эквивалентны. А херню с присвоением строки я и вовсе не понял. Если хочешь присваивать строки и не получать сегфолты, то используй лучше strcpy.

Deleted
()
Ответ на: комментарий от Deleted

a[4] и *(a+4) эквивалентны, если char *a. А если char a[128], то уже не правильно. Это я вычитал в K&R, который сейчас у меня перед глазами, могу даже страницу назвать или сфотографировать.

momo
() автор топика
Ответ на: комментарий от momo

У тебя пиратский K&R. Или пиратские глаза.

#include <stdio.h>
#include <string.h>

int main()
{
    char a[ 32 ];
    strcpy( a, "Do your homework!" );
    char c = *( a + 3 );
    printf( "2momo\n%s\n%c\n", a, c );
    return 0;
}
ecko@peka:~$ ./test 
2momo
Do your homework!
y

Deleted
()
Ответ на: комментарий от momo

Это будет эквивалентно переходу поинтера на а[5]

Deleted
()
Ответ на: комментарий от momo

Прекрати тупить, я тебе обо всём написал.

#include <stdio.h>
#include <string.h>

int main()
{
    char a[ 32 ];
    strcpy( a, "MOMO, you are stupid!" );
    printf( "%s\n%s\n", a, a + 5 );
    return 0;
}

ecko@peka:~$ ./test 
MOMO, you are stupid!
 you are stupid!

Deleted
()
Ответ на: комментарий от momo

Это да. Здесь s будет иметь тип char* const, т. е. константный указатель на неконстантную память. А указывать он будет на массив из 128 байт, выделенный тут же, в стеке.

intelfx ★★★★★
()
Ответ на: комментарий от Deleted
#include <stdio.h>

int main()
{
	char *s = (char[128]){};
	char s2[128];
	printf("%lu\n%lu\n",sizeof(s), sizeof(s2) );
	return 0;
}
 ./a.out
8
128

что я сделал не так?

momo
() автор топика
Ответ на: комментарий от momo

что я сделал не так?

Не научился читать. Прочти полностью ту ветку комментариев. Эти записи не эквивалентны.

Deleted
()
Ответ на: комментарий от momo

Чувак, ты объявляешь строки неинициализированными поинтерами, вместо гуглежа и чтения K&R, лежащего у тебя под рукой, ты пишешь на ЛОР. Попутно ты пытаешься плюсовать строки.

И после этого из нас двоих я тупой? Шёл бы ты отсюда, уважаемый.

Deleted
()
Ответ на: комментарий от intelfx

Соответственно, сам s изменить нельзя (т. е. s++ или s = что-угодно некорректны), но сделать *(s + 5) можно запросто.

intelfx ★★★★★
()
Ответ на: комментарий от Deleted

Я почему-то думал, что иначе мы отловим ошибку О_о неужто это в крестах, а в сях нет?

Как же я люблю, когда крестовое балаболы рассуждают о сишке - это так мило. Ещё курлыкают о том, что я не прав. Я, помазанник божий на владычество над сишкой, я Абсолютный Царь не прав. Рили? Куллстори.

Да, в сишке n может быть не константой.

Мой вариант лаконичнее.

Твой вариант не эквивалентен варианту с маллоком, а мой эквивалентен.

У меня указатель, как после маллока, у тебя же массив. О чем тебе уже не раз пацаны намекнули.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.