Как я могу получить блок памяти из функции и записать его в файл? - PullRequest
1 голос
/ 21 июля 2009

Я хочу записать данные «somebytes», которые я получаю из функции с именем NextUnit(), в файл с именем «output.txt», но написанный мной код не работает. Когда я открываю файл, он не выглядит как мои "somebytes". Вот код:

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

char* NextUnit()
{
    char Unit[256];
    strcpy(Unit,"somebytes");
    return &Unit[0];
}

int main()
{
    FILE *ourfile;
    ourfile=fopen("output.txt","wb");
    char* somedata;
    somedata=NextUnit();
    printf("%s\n",somedata);
    fwrite(somedata,1,strlen(somedata),ourfile); 
    fclose(ourfile);
}

Ответы [ 9 ]

3 голосов
/ 21 июля 2009

Вы возвращаете локальный адрес из функции (или освобожденный адрес стека). Который затем изменяется после вызова следующей функции.

Эфир просто возвращает глобальную константу

const char* NextUnit() { return "somebytes"; }

или скопируйте его в новую структуру памяти, которую потом потребуется также позже ...

char* NextUnit() 
{ 
    char* newstr = new char[256]; 
    strcpy(newstr,"somebytes"); 
    return newstr;
}

// some code later
char* tmpstr = NextUnit();

// do writing stuff

// free memory
delete tmpstr;
1 голос
/ 21 июля 2009

Если вы используете C ++, следующий способ гораздо лучше:

#include <iostream>
#include <string>

using namespace std;

int main(int argc, char ** argv)
{
    ofstream outFile;

    outFile.open("output.txt");
    outFile << "someBytes";
    outFile.close();

    return 0;
}

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

1 голос
/ 21 июля 2009

Я бы переписал это так:

char *NextUnit(char *src)
{
    strcpy(src, "somebytes");
    return src;
}

Таким образом, вы можете решить, что делать с переменной вне реализации функции:

char Unit[256];
char *somedata = NextUnit(Unit);
1 голос
/ 21 июля 2009

вы возвращаете местный адрес функция. Эфир просто верни

const char * NextUnit () {return "somebytes"; }

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

Мне не хватает mojo, чтобы прокомментировать цитируемый ответ, поэтому я должен поставить это как новый ответ.

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

Ваш код возвращает адрес локальной переменной внутри функции NextUnit (). Не делай этого. Это плохо. Делай, что он предложил.

1 голос
/ 21 июля 2009

Вы объявили Unit[256] в стеке в подпроцедуре.Но когда ваш NextUnit() возвращается, переменная, для которой он был задан, выходит из области видимости, и вы больше не указываете на допустимую память.

Рассмотрите возможность выделения памяти с помощью new, а затем освободите ее ввызывающий или передающий ему указатель на заранее выделенную память.

0 голосов
/ 21 июля 2009

Объявить Unit как static:

char* NextUnit()
{
  static char Unit[256];
  strcpy(Unit,"somebytes");
  return &Unit[0];
}

Но если вы используете компилятор C ++, вам следует рассмотреть возможность использования std::string вместо char*. std::string более безопасен и выполнит все задания по выделению / освобождению.

0 голосов
/ 21 июля 2009

"Unit" объявлен как локальная переменная внутри NextUnit, которая на самом деле является переменной "стека", что означает, что его время жизни только до тех пор, пока NextUnit не вернется.

Итак, хотя NextUnit еще не вернулся, копирование «somebytes» в него - это нормально, равно как и его распечатка. Как только NextUnit возвращается, Unit освобождается из стека, и указатель somedata в main не будет указывать на что-то допустимое.

Вот быстрое решение. Я до сих пор не рекомендую писать программы таким образом, но это наименьшее количество изменений.

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

char Unit[256];

char* NextUnit()
{

    strcpy(Unit,"somebytes");
    return &Unit[0];
}

int main()
{
    FILE *ourfile;
    ourfile=fopen("output.txt","wb");
    char* somedata;
    somedata=NextUnit();
    printf("%s\n",somedata);
    fwrite(somedata,1,strlen(somedata),ourfile); 
    fclose(ourfile);
}

Это работает, но бессмысленно возвращать адрес модуля, когда он на самом деле глобален!

0 голосов
/ 21 июля 2009

У вас есть несколько проблем здесь. Основным, я думаю, является то, что NextUnit () выделяет буфер в стеке, и вы фактически выходите из области видимости, когда пытаетесь вернуть адрес.

Вы можете исправить это в решении в стиле C, используя неправильное пространство для буфера и возвращая указатель, который возвращает malloc.

Я думаю, что первым шагом может быть переписать код на что-то более похожее на следующее:

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

char* NextUnit()
{
    char *Unit = (char *)malloc( 256 );
    memset(Unit, 0, sizeof(Unit));
    strcpy(Unit,"somebytes");
    return Unit;
}

int main()
{
    FILE *ourfile;
    ourfile=fopen("output.txt","wb");
    char* somedata;
    somedata=NextUnit();
    printf("%s\n",somedata);
    //fwrite(somedata,1,strlen(somedata),ourfile);
    fprintf(ourfile, somedata); 
    free(somedata);
    fclose(ourfile);
}
0 голосов
/ 21 июля 2009

NextUnit возвращает адрес модуля, который является массивом, локальным для этой функции. Это означает, что он размещается в стеке и «освобождается» при возврате функции, что делает возвращаемое значение недействительным.

Для решения этой проблемы вы можете:

  • Динамически назначать новую строку каждый раз, когда вызывается NextUnit. Обратите внимание, что в этом случае вам придется удалить память впоследствии.
  • Создать глобальную строку. Это хорошо для небольшого «тестового» приложения, но обычно использование глобальных переменных не рекомендуется.
  • Пусть main выделит строку (динамически или в стеке), передаст ее в качестве параметра в NextUnit и получит копию NextUnit в эту строку.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...