LINUX.ORG.RU

Под линуксом работает правильно, под MinGW — нет


0

2

Понадобилось срочно прочитать из бинарного файла большое количество записей следующей структуры: 3 32-разрядных целых, текстовая строка произвольной длины с 0 на конце. Первое целое — длина данной записи в байтах. После последней записи идёт известное число многократно больше длины любой записи.

Набросал следующую программу:

int fd;
int recordsize, data1, data2; 
char filename[1000];
int indexposition;
...
	fd = open( "SOMEFILE.XYZ", O_RDONLY);
	lseek( fd, indexposition, SEEK_SET);
	read( fd, &recordsize, 4); 
	while ( recordsize < infostart ) {
		//lseek( fd, indexposition+4, SEEK_SET);
		read( fd, &data1, 4);
		//lseek( fd, indexposition+8, SEEK_SET);
		read( fd, &data2, 4); 
		//lseek( fd, indexposition+12, SEEK_SET);
		read( fd, filename, recordsize - 12);
		...
		//indexposition += recordsize;
		//lseek( fd, indexposition, SEEK_SET);
		read( fd, &recordsize, 4);
	};

Под 32-разрядным линуксом с GCC 4 в таком виде нормально собирается и работает. Под виндоуз с GCC 3 нормально читает 1-ю запись и зацикливается в районе 2-ой—3-ей, но если раскомментировать строки с lseek — работает.

Кто-нибудь может объяснить причину?

В пропущенных частях никакого доступа к диску нет.

★★★★★

Ты бы для начала проверил статус выполнения твоих функций open, lseek, read. А то мало ли чего, errno бы подсказал.

линуксом с GCC 4

виндоуз с GCC 3



GCC3 и GCC4 настолько разные, что вендупс/линупс здесь может быть не так важно. Если хочешь корректного сравнения, порадуй свою семёрочку свеженьким mingw.

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

поддерживаю O_BINARY

и ещё нагляднее читать целым куском :

struct record {
  uint32_t data1;
  uint32_t data2;
  char filename[1000];
  uint32_t recordsize;
} __attribute__((packed)) record;
int fd;
fd=open(filename,O_RDONLY|O_BINARY|O_NOCTTY);
size=read(fd,&record,sizeof(record));
if (size==sizeof(record)) {
  // Well !!
}
если файл записан схожем образом, но на другой архитектуре, надо будет отработать endianes

MKuznetsov ★★★★★
()

Ненависть ненависть ненависть

Зачем использовать низкоуровневые системные вызовы, когда в стандарте Си есть FILE* ?!

Manhunt ★★★★★
()
Ответ на: комментарий от rg-400

Что там читает read - это проблемы исключительно самого read'a

MINGW использует MSVCRT.
И все отсылки к линуксовой документации (что там в мане к опену есть и что там рид читает в линуксе) выглядят как минимум странно.

Всю жизнь в досе и винде для чтения двоичный данных нужно было открывать файлы явно в двоичном режиме.
http://msdn.microsoft.com/en-us/library/z0kc8e3z.aspx

О чём тут вообще ещё можно спорить?
Какой нах man 2 open в mingw?

anonymous
()
int recordsize, ...
read( fd, &recordsize, 4);

А вы уверены, что на вашей системе и вашем компиляторе sizeof(int) == 4?

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

> Вывести на печать текущую позицию в файле не пробовал?

Какой функцией? А то, что читает не оттуда я и так понял :)

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

> use visual studio, luke

Нет возможности ничего устанавливать. Стоит MinGW Studio года 2003-го, но я не разобрался как в ней задать язык исходников Си. Только C++, который я знаю ещё хуже.

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

> А если использовать mingw вот отсюда: http://tdm-gcc.tdragon.net/ например?

Спасибо за ссылку, но сейчас попробовать не могу.

Да и на mingw.org уже есть 4-я версия.

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

> fd = open( «SOMEFILE.XYZ», O_RDONLY | O_BINARY);

Спасибо, заработало!

И ведь знал же про такую деталь, но в нужный момент не вспомнил.

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

> нагляднее читать целым куском

Спасибо за совет, но уже сказали, что строка переменной длины :)

В 2 приёма можно.

Кстати, какой прок в O_NOCTTY, если там заведомо реальный файл?

question4 ★★★★★
() автор топика
Ответ на: Ненависть ненависть ненависть от Manhunt

> Зачем использовать низкоуровневые системные вызовы, когда в стандарте Си есть FILE* ?!

Какой функцией из него читать блоки заданного размера, чтобы не затыкалось на управляющих символах? Как переходить к заданной позиции (в байтах)?

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

> читай через fopen/fread/fclose.

Из этого же файла одновременно должно идти чтение блоков данных с произвольных точек. data1 и data2 — положение и длина. Открывать файл одновременно и open и fopen?

question4 ★★★★★
() автор топика
Ответ на: комментарий от rg-400

> Может fscanf подойдет?

Я вообще хотел mmap и sscanf :) Но оказалось, что в MinGW mmap не поддерживается (или тогда не поддерживался).

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

> А вы уверены, что на вашей системе и вашем компиляторе sizeof(int) == 4?

Да. 32-разрядная Winows XP и 32-разрядный GCC без опций кросс-компиляции.

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

> а вообще приведи полный код, без всяких "..."

А это и был почти полный код. Убрал только printf-ы. В окончательном варианте будет ещё чтение блоков данных из других мест файла и их запись в отдельные файлы. Но это уже не сейчас — на ходу засыпаю.

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

> Какой функцией из него читать блоки заданного размера

fread

чтобы не затыкалось на управляющих символах?


fopen(filename, «rb»)

Как переходить к заданной позиции (в байтах)?


fseek

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

>Из этого же файла одновременно должно идти чтение блоков данных с произвольных точек. data1 и data2 — положение и длина. Открывать файл одновременно и open и fopen?

зачем вообще open использовать? открой один файл два раза через fopen и все.

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

и ещё нагляднее читать целым куском :

«текстовая строка произвольной длины с 0 на конце»

TC эту строку изначально читает одним большим куском :)

read( fd, filename, recordsize - 12);

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

TC эту строку изначально читает одним большим куском :)

read( fd, &recordsize, 4);
s0L
()
Ответ на: комментарий от buddhist

>Поддерживаю. Системные вызовы в пользовательских программах не нужны (да и в большинстве системных тоже).

С open всё нормально. Есть такой системный вызов, но есть и libc-функция(man 2 open/man 3 open).

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