Запись двоичного файла в файл извлекает неверные данные из предыдущих несвязанных команд popen в C

Так что этот код работает сам по себе, но когда я использую его со своей основной программой, он как-то подтягивает какие-то, казалось бы, совершенно не связанные части кода и записывает их в файл, который я пишу... Все компилируется без проблемы, поэтому я знаю, что это не проблема определения или проблема указателя, и все остальное записывается правильно, но каким-то образом я получаю более 3200 байтов материала, к которому структура не имеет никакого отношения, и записываю его по адресу 0x1 в файл, который также не является частью структуры...

struct a {
    unsigned long addr; //File address
    int sz; //Num Bytes
    unsigned long pos; // Buffer Address
};

// Many more than this, but you get the general struct idea..
struct a as[][3] = {
    {{ 0xF245, 5, 0x6F02C4 }},
    {{ 0x471D, 128, 0x65892 }},
    {{ 0x6198F, 12, 0xA4092 }}
}

//Failing code
        fdin = fopen(files[FIRSTFILE]->filename, "rb");

        fdout = fopen(files[SECONDFILE]->filename, "r+b");

        if (!fdin) {
            fprintf(stderr, "Unable to open %s\n", files[FIRSTFILE]->filename);
            fclose(fdin);
            cleanup(ONSCREEN);
            return EXIT_FAILURE;
        }

        if (!fdout) {
            fprintf(stderr, "Unable to open %s\n", files[SECONDFILE]->filename);
            fclose(fdout);
            fclose(fdin);
            cleanup(ONSCREEN);
            return EXIT_FAILURE;
        }

У меня здесь есть другой код, но ни один из них не читает из файла и не записывает в другой, как этот. Но где-то здесь он неправильно записывает как минимум 3200 байтов в диапазоне адресов 0x1-0xC88 в файле и извлекает данные, которые я использую в функциях popen перед всем этим.

        for (int i = 0; i <= (sizeof(buffer) / sizeof(buffer[0])); i++) {

            memset(buffer, 0, sizeof(buffer));
            fseek(fdin, as[i]->pos, SEEK_SET);
            fread(buffer, 1, as[i]->sz, fdin);

            fseek(fdout, as[i]->addr, SEEK_SET);
            fwrite(buffer, 1, as[i]->sz, fdout);
        }

        if(fclose(fdout)==EOF || fclose(fdin)==EOF) {
            logit(ONSCREEN, "Error closing files.\n\n");
            cleanup(ONSCREEN);
            return EXIT_FAILURE;
        }
        fflush(fdin);
        fflush(fdout);

Вот фрагмент кода из основной программы, из которой каким-то образом она извлекает информацию:

        sleep(1);
        memset(command, 0x00, 256);
        sprintf(command, "./somecommand");
        fp = popen(command, "r");
        if (fp == NULL) {
            logit(ONSCREEN, "popen failed.");
            cleanup(ONSCREEN);
            return EXIT_FAILURE;
        }

        while(fgets(store, sizeof(store), fp)) {
            if (strstr(store, "Expected Output")) {
            break;
            }
        }
        pclose(fp);
        fflush(fp);

Опять же, все эти функции прекрасно работают сами по себе, но когда они объединены в одну функцию, они плохо работают вместе... Файлы (ФАЙЛ *fp, *fdin, *fdout) имеют разные имена, а хранилище массив символов называется иначе, чем буфер. Что я здесь сделал не так?

Кажется, что-то небезопасное в использовании popen и fopen в одной и той же функции, или что-то, что я не убираю здесь должным образом ...?


person Chu    schedule 10.03.2013    source источник
comment
Можете ли вы опубликовать небольшой автономный компилируемый пример? Трудно понять, как фрагменты кода, которые вы опубликовали, могут взаимодействовать. Кроме того, вы не проверяете возвраты от ваших вызовов ввода-вывода, так что, возможно, ошибка ввода-вывода влияет на результаты? А какой тип buffer? Я надеюсь, что это массив, а не указатель.   -  person Michael Burr    schedule 10.03.2013
comment
Если вам не удалось открыть fdout, использование fclose(fdout) в пути ошибки приведет к сбоям. Аналогично для fdin. Это не ваша непосредственная проблема; это потенциальная проблема в ваших путях ошибок. Вы не проверяете свои звонки fread() и fwrite(); это беспокоит (особенно fread()).   -  person Jonathan Leffler    schedule 10.03.2013
comment
Ну, я не думаю, что это ошибка ввода-вывода, потому что он делает все, что должен. эта дополнительная модификация каким-то образом происходит ПОВЕРХ того, что она уже делает... буфер представляет собой массив char[256].   -  person Chu    schedule 10.03.2013
comment
Ба, не знал, что Enter добавил комментарий... Я пытался отделить строку, через несколько минут получу рабочий компилятор и выложу.   -  person Chu    schedule 10.03.2013
comment
Кроме того, вы почти наверняка хотите < вместо <= в этом: for (int i = 0; i <= (sizeof(buffer) / sizeof(buffer[0])); i++)   -  person Michael Burr    schedule 10.03.2013
comment
Вы можете редактировать собственные комментарии до 5 минут; «возврат означает подчинение» ловит меня время от времени, даже сейчас.   -  person Jonathan Leffler    schedule 10.03.2013
comment
Как размер буфера, из которого вы читаете/записываете, имеет прямое отношение к индексу массива as, из которого вы получаете позицию файла и размеры ввода-вывода? Это похоже на ошибку, даже если массив as[] имеет то же количество элементов, что и buffer[] в данный момент.   -  person Michael Burr    schedule 10.03.2013


Ответы (1)


В вашем примере as[] имеет 3 элемента (ваш реальный код может иметь другое число)

// Many more than this, but you get the general struct idea..
struct a as[][3] = {
    {{ 0xF245, 5, 0x6F02C4 }},
    {{ 0x471D, 128, 0x65892 }},
    {{ 0x6198F, 12, 0xA4092 }}
}

Однако вы используете количество элементов в buffer (которое в комментарии вы называете char buffer[256] для его индексации:

   for (int i = 0; i <= (sizeof(buffer) / sizeof(buffer[0])); i++) {

        memset(buffer, 0, sizeof(buffer));
        fseek(fdin, as[i]->pos, SEEK_SET);
        fread(buffer, 1, as[i]->sz, fdin);

        fseek(fdout, as[i]->addr, SEEK_SET);
        fwrite(buffer, 1, as[i]->sz, fdout);
    }

Измените цикл for на (обратите внимание, что тест изменен с <= на <):

  for (int i = 0; i < (sizeof(as) / sizeof(as[0])); i++)  

Наконец, я думаю, что вы излишне усложняете вещи (и, возможно, с ошибками), используя двумерный массив для as без всякой причины. пытаться:

struct a as[] = {
    { 0xF245, 5, 0x6F02C4 },
    { 0x471D, 128, 0x65892 },
    { 0x6198F, 12, 0xA4092 }
}


// ...
   for (int i = 0; i < (sizeof(as) / sizeof(as[0])); i++) {

        memset(buffer, 0, sizeof(buffer));
        fseek(fdin, as[i].pos, SEEK_SET);
        fread(buffer, 1, as[i].sz, fdin);

        fseek(fdout, as[i].addr, SEEK_SET);
        fwrite(buffer, 1, as[i].sz, fdout);
    }
person Michael Burr    schedule 10.03.2013
comment
Теперь я понимаю ваш вопрос, я только что понял, что неправильно разместил это... при переименовании того, что находится в моем коде, на что-то менее показательное для того, на чем основан мой проект, я по ошибке изменил это на буфер, а не как... В моем код правильно указывает размер структуры, а не буфера. Почти получил рабочий код для публикации. - person Chu; 10.03.2013
comment
Странно, в тестовом коде, который я скопировал и провел меньший тест, он работал без проблем. Я должен посмотреть, что отличается в моем основном коде, и убедиться, что я не сделал больше неправильных ссылок. , Однако спасибо за другую информацию, я определенно усложнял это. Я бы отметил это как ответ, но это будет вводить в заблуждение, поскольку это не совсем ответ на основной вопрос, и это не позволит мне проголосовать за него, потому что у меня недостаточно представителей... - person Chu; 11.03.2013
comment
На самом деле я думаю, что это исправило это, потому что после того, как я внес эти изменения, он работает правильно. Тогда спасибо! - person Chu; 11.03.2013