简体   繁体   中英

How can I get a block of memory from a function and write it to a file?

I want to write the data "somebytes" that I get from a function called NextUnit() to a file named "output.txt", but the code that I wrote does not work. When I open the file, it does not look like my "somebytes". Here is the code:

#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);
}

You are returning the local address from a function (aka released stack address). Which is then changed once you call the next function.

Ether just return a global constant

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

or copy it into a new memory structure, which you will then need to also free later...

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;

You've declared Unit[256] on the stack in a subprocedure. But when your NextUnit() returns, the variable that was scoped to it goes out of scope, and you are no longer pointing to valid memory.

Consider allocating the memory with new , and then releasing it in the caller, or having the caller pass down a pointer to preallocated memory.

you are returning the local address of a function. Ether just return

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

so it's constant, or copy it into a new memory stucture, which you will then need to also free later...

I don't have enough mojo to comment on the quoted answer, so I have to put this as a new answer.

His answer is trying to say the right thing, but it came out wrong.

Your code is returning the address of a local variable inside the NextUnit() function. Don't do that. Its bad. Do what he suggested.

I would rewrite it like this:

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

This way you can decide what to do with the variable outside the function implementation:

char Unit[256];
char *somedata = NextUnit(Unit);

If you are using C++, the following is a much better way to go about this:

#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;
}

And, once you are comfortable with that, the next thing to learn about is RAII .

NextUnit returns the address of Unit, which is an array local to that function. That means that it is allocated on the stack, and "released" when the function returns, making the return value non-valid.

To solve this problem you can:

  • Dynamically allocate a new string each time NextUnit is called. Note that in that case you will have to delete the memory afterwards.
  • Create a global string. That's fine for a small "test" application, but generally use of global variables is discouraged.
  • Have main allocate a string (either dynamically or on the stack), pass it as a parameter to NextUnit, and have NextUnit copy to that string.

You have a few problems here. The main one, I think, is that NextUnit() is allocating the buffer on the stack and you're effectively going out of scope when you try to return the address.

You can fix this in a C-style solution by mallocing space for the buffer and returning the pointer that malloc returns.

I think a first step might be to rewrite the code to something more like the following:

#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);
}

"Unit" declared as a local variable inside NextUnit which is actually a "stack" variable meaning that it's lifetime is only as long as NextUnit hasn't returned.

So, while NextUnit hasn't returned yet, copying "somebytes" to it is ok, as is printing it out. As soon as NextUnit returns, Unit is released from the stack and the pointer somedata in main will not be pointing to something valid.

Here is quick fix. I still don't recommend writing programs this way this way, but it's the least changes.

#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);
}

That works but it's kindof pointless returning the address of Unit when it's actually Global!

Declare Unit as static :

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

But if you use C++ compiler you should consider using std::string instead of char* . std::string is more safe and will do all allocation/deallocation jobs for you.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM