Pointers and assignment in a sub-function - c

I have a small program that creates a semver struct with some variables in it:
typedef struct {
unsigned major;
unsigned minor;
unsigned patch;
char * note;
char * tag;
} semver;
Then, I would like to create a function which creates a semver struct and returns it to the caller. Basically, a Factory.
That factory would call an initialize function to set the default values of the semver struct:
void init_semver(semver * s) {
s->major = 0;
s->minor = 0;
s->patch = 0;
s->note = "alpha";
generate_semver(s->tag, s);
}
And on top of that, I would like a function to generate a string of the complete semver tag.
void generate_semver(char * tag, semver * s) {
sprintf( tag, "v%d.%d.%d-%s",
s->major, s->minor, s->patch, s->note);
}
My problem appears to lie in this function. I have tried returning a string, but have heard that mallocing some space is bad unless you explicitly free it later ;) In order to avoid this problem, I decided to try to pass a string to the function to have it be changed within the function with no return value. I'm trying to loosely follow something like DI practices, even though I'd really like to separate the concerns of these functions and have the generate_semver function return a string that I can use like so:
char * generate_semver(semver * s) {
char * full_semver;
sprintf( full_semver, "v%d.%d.%d-%s",
s->major, s->minor, s->patch, s->note);
return full_semver; // I know this won't work because it is defined in the local stack and not outside.
}
semver->tag = generate_semver(semver);
How can I do this?

My problem appears to lie in this function. I have tried returning a string, but have heard that mallocing some space is bad unless you explicitly free it later.
Explicitly freeing dynamically allocated memory is required to avoid memory leaks. However, it is not necessarily a task that the end users need to perform directly: an API often provides a function to deal with this.
In your case, you should provide a deinit_semver function that does the clean up of memory that init_semver has allocated dynamically. These two functions behave in a way that is similar to constructor and destructor; init_semver is not a factory function, because it expects the semver struct to be allocated, rather than allocating it internally.
Here is one way of doing it:
void init_semver(semver * s, int major, int minor, int pathc, const char * note) {
s->major = major;
s->minor = minor;
s->patch = pathc;
size_t len = strlen(note);
s->note = malloc(len+1);
strcpy(s->note, note);
s->tag = malloc(40 + len);
sprintf(s->tag, "v%d.%d.%d-%s", major, minor, patch, note);
}
void deinit_semver(semver *s) {
free(s->note);
free(s->tag);
}
Note the changes above: rather than using fixed values for the components of struct semver, this code takes the values as parameters. In addition, the code copies the note into a dynamically allocated buffer, rather than pointing to it directly.
The deinit function does the clean-up by free-ing both fields that were allocated dynamically.

A char * on its own is just a pointer to memory. To accomplish what you want you will either need to instead use a fixed size field, i.e. char[33], or you can dynamically allocate the memory as needed.
As it is, your generate_semver function is attempting to print to an unknown address. Let's look at one solution.
typedef struct {
unsigned major;
unsigned minor;
unsigned patch;
char note[32];
char tag[32];
} semver;
Now, in your init_semver function, the line previously s->note = "alpha"; will become a string copy, as arrays are not a valid lvalue.
strncpy(s->note, "alpha", 31);
s->note[31] = '\0';
strncpy will copy a string from the second parameter to the first up to the number of bytes in the third parameter. The second line ensures that a trailing null terminator is in place.
Similarly, in the generate_semver function, it would directly work in the buffer:
void generate_semver(semver * s) {
snprintf( s->tag, 32, "v%d.%d.%d-%s",
s->major, s->minor, s->patch, s->note);
}
This will directly print to the array in the structure, with a maximum character limit. snprintf does append a trailing null terminator (unlike strncpy), so we don't need to worry about adding it ourselves.

You mention having to free allocated memory, and then say: "In order to avoid this problem". Well, it's not so much a problem, but rather a necessity of the C language. It's common to have functions that allocate memory, and require the caller to free it again.
The idiomatic way is to have a pair of "create" and "destroy" functions. So I'd suggest doing it like this:
// Your factory function
semver* create_semver() {
semver* instance = malloc(sizeof(*instance));
init_semver(instance); // will also allocate instance->tag and ->note
return instance;
}
// Your destruction function
void free_semver(semver* s) {
free(semver->tag);
free(semver->note);
free(semver);
}

Related

Return string from function that will be used to create a DLL

I need to create a DLL file that can be used for MS Access and other applications that will return a string when fed parameters. I am fairly familiar with MS Access but an absolute novice at C.
Following is the code I am experimenting with. I want to be able to issue a call like getstring(32.1, 123.2, "here", 25) and have it return a string of up to 60 characters in length. The actual code works fine and buf contains the string I want when it's finished running but I am having trouble handing it back to the calling function.
UPDATE:
Ok, I've worked out how to create a DLL and run a function from VBA but I am still struggling to understand how to return strings. I think if I can get this to work, I can work out my whole project. By running the following code I can get VBA to return the square of the input number e.g. feed it a parameter of 10 and I get an answer of 100
double _stdcall square(double *x)
{
return *x * *x;
}
However when I run the following code in Excel and feed it a parameter of "test" all I get back is a square box character.
char _stdcall Boxx(char *x)
{
return *x;
}
In this case all I want it to return is what I entered. If I can get it to return that I hope to be able to replace that with the actual result. Any suggestions?
char * Getstring(double lat, double lon, char *name, double zoom)
{
char buf[60] = { '\0' }; // Set the max length of the final link string
int ret = GenShortDroidMapUrl(lat, lon, zoom, name, buf, sizeof(buf) - 1);
return buf;
}
In the posted code, buf[] is an automatic variable whose lifetime ends after the Getstring() function has returned. Since buf[] will no longer exist when control of the program has returned to the caller, a pointer to this variable will be invalid after Getstring() has returned.
One solution is to pass an additional argument into the Getstring() function to accept the string, along with a size argument. Since buf will decay to a pointer in the function call, the sizeof operator can't be used in Getstring() to find the size of the array, but buf_sz holds this value:
char * Getstring(char *buf, size_t buf_sz, double lat, double lon, char *name, double zoom)
{
// buf[] has been zero-initialized in the caller
int ret = GenShortDroidMapUrl(lat, lon, zoom, name, buf, buf_sz - 1);
return buf;
}
Another option that does not require changing the function signature is to dynamically allocate storage for the returned string. Again, buf is a pointer to char in Getstring(), so the sizeof expression in GenShortDroidMapUrl() will need to be replaced; this time the constant BUF_SZ has been used here. Note that the malloced memory will need to be freed by the caller later.
#include <string.h>
#define BUF_SZ 60
/* ... */
char * Getstring(double lat, double lon, char *name, double zoom)
{
char *buf = malloc(sizeof *buf * BUF_SZ);
memset(buf, '\0', BUF_SZ);
/* Or use calloc() and avoid the call to memset() */
// char *buf = calloc(BUF_SZ, sizeof *buf);
int ret = GenShortDroidMapUrl(lat, lon, zoom, name, buf, BUF_SZ - 1);
return buf;
}
If Getstring() is part of a library, you need to ensure that the deallocator function matches the allocation functions. That is, there may be problems if the version of malloc() or calloc() that Getstring() is linked against differs from the version of free() that the calling code is linked against. One solution is to provide a deallocation function with the library. This could be as simple as wrapping free() in another function to be used by the caller to ensure that a matching deallocator is used. Here, the function DLL_Free() is part of the DLL, and malloc(), calloc(), and free() would all be linked against the same library when the DLL is created. The caller that uses Getstring() would use DLL_Free() to deallocate. From the caller, free() may not work as expected to deallocate the memory allocated by Getstring(), but DLL_Free() would since this deallocator uses the version of free() that matches the allocators used in the DLL.
/* Deallocation function included in DLL that matches allocation
* functions used in library
*/
void DLL_Free(void *ptr)
{
free(ptr);
}
There are many ways to return a string, but respect the lifetime of buffers:
Can a local variable's memory be accessed outside its scope?
One is to let the caller supply the buffer. Return how much space would have been needed, and a simple comparison will tell you whether it was enough.
Another is to use a static, optionally thread-local, buffer. Beware the restrictions on concurrency and reentrancy.
And finally, you can allocate it dynamically. Remember that it has to be freed with the same system, which on windows often means you have to manually export the way to free it from your DLL. Better not to reinvent the wheel, look at BSTRs for example.
You could either declare buf static and let the function return const char *. But that would not be reentrant. So another solution is to return strdup(buf), which will return a copy that the caller needs to free after use (otherwise you will have a memory leak).

Memcpy with a void pointer

I am having trouble with the memcpy function. I need a function that stores data into a void pointer. Here is a simple example of it:
void saveData(void* data)
{
char inputData[] = "some data";
memcpy((char*)data, inputData, sizeof(inputData));
}
However I get segmentation errors when I do this, even though it compiles just fine. My function argument has to be a void pointer because I may have different data formats to input and I may not know the size of the data ahead of time. Could somebody tell me what I am doing wrong?
Please and thank you.
***UPDATE:
Thanks all for the helpful responses. As most of you pointed out, I did not initialize void* data. That fixed it.
Now my question is: when I do dynamic allocation for the void* data (or even char* data), I give it a size, but when I do memcpy, it allows me to write an ever bigger string than I first assigned space for. I also tried just doing char* data, and the same thing happens. This is my sample code:
char inputData[] = "123456789";
void* data1 = malloc(5*sizeof(char));
char* data2 = (char*)malloc(5*sizeof(char));
memcpy(data1,inputData,sizeof(inputData));
memcpy(data2,inputData,sizeof(inputData));
When I print out the results, the entire string of inputData get copied even though I only allocated enough space for 5 chars. Shouldn't that give me an error?
Your function parameter data needs to point to somewhere that there is memory available.
You could do something like this:
int main()
{
char myString[256];
saveData((void*)myString);
}
If you prefer to use malloc and free, then your code would be more like this:
int main()
{
char* myString = (char*)malloc(256);
saveData((void*)myString);
free(myString);
}
..the trouble with both of these is that you don't know how long the string needs to be. It would be far safer/easier to use std::string.
std::string myString; // an empty string
myString += "some data"; // append a string
Note that the size of the source is not given by sizeof but by strlen. Assuming the caller does not want to allocate memory, you need to malloc storage and have the void* store a handle to that. Given the save function calls malloc, I'd set up a corresponding release function.
bool saveData(void** retSave, const char* input)
{
bool success = false;
size_t storageSize = strlen(input) + 1;
void* store = malloc(storageSize);
if (store)
{
memcpy(store, input, storageSize);
success = true;
}
return success;
}
void releaseSavedData(void* savedData)
{
free(savedData);
}
int main()
{
void* saveHandle = 0;
bool ok = saveData(&saveHandle, "some data");
if (ok)
{
releaseSavedData(saveHandle);
}
return 0;
}
data needs to point to somewhere you have access to write. The null pointer area you don't have access to (unless you're running DOS or something).
Use malloc to allocate a chunk of memory to copy from inputData to.
If you don't know the size of the data ahead of time, the only way to get this to work is to malloc some arbitrarily large buffer and make sure you NEVER copy more than that # of bytes into the void*. Not the best design, but it will work.
Also, don't forget to allocate an extra byte for the NULL char on the end of the string, and don't forget to actually put the null on the end of the memory buffer. In the example above, your string in data won't have a NULL on the end.

Sacrificing expression of intent for memory management

I'm pretty new at C programming, and this type of thing keeps popping up. As a simple example, suppose I have a struct http_header with some char pointers:
struct http_header {
char* name;
char* value;
};
I want to fill an http_header where value is the string representation of an int. I "feel" like, semantically, I should be able to write a function that takes in an empty header pointer, a name string, and an int and fills out the header appropriately.
void fill_header(struct http_header *h, char* name, int value)
{
h->name = name;
char *value_str = malloc(100);
sprintf(value_str, "%d", value);
h->value = value_str;
}
int main(int argc, const char * argv[])
{
struct http_header h;
char *name = "Header Name";
int val = 42;
fill_header(&h, name, val);
...
free(h.value);
}
Here, the calling code reads exactly as my intent, but in this case I'm creating the value string dynamically, which means I'd have to free it later. That doesn't smell right to me; it seems like the caller then knows too much about the implementation of fill_header. And in actual implementations it may not be so easy to know what to free: consider filling an array of http_headers where only one of them needed to have its value malloced.
To get around this, I'd have to create the string beforehand:
void fill_header2(struct http_header *h, char* name, char *value_str)
{
h->name = name;
h->value = value_str;
}
int main(int argc, const char * argv[])
{
struct http_header h;
char *name = "Header Name";
int value = 42;
char value_str[100];
sprintf(value_str, "%d", value);
fill_header2(&h, name, value_str);
}
As this pattern continues down the chain of structures with pointers to other structures, I end up doing so much work in top level functions the lower level ones seem hardly worth it. Furthermore, I've essentially sacrificed the "fill a header with an int" idea which I set out to write in the first place. I'm I missing something here? Is there some pattern or design choice that will make my life easier and keep my function calls expressing my intent?
P.S. Thanks to all at Stackoverfow for being the best professor I've ever had.
Well, I would go with the first approach (with a twist), and also provide a destroy function:
struct http_header *make_header(char *name, int value)
{
struct http_header *h = malloc(sizeof *h);
/* ... */
return h;
}
void destroy_header(struct http_header *h)
{
free(h->name);
free(h);
}
This way the caller doesn't have to know anything about http_header.
You might also get away with a version that leaves the main allocation (the struct itself) to the caller and does it's own internal allocation. Then you would have to provide a clear_header which only frees that fill allocated. But this clear_header leaves you with a partially-valid object.
I think your problem is simply that you are programming asymmetrically. You should once and for all decide who is responsible for the string inside your structure. Then you should have two functions, not only one, that should be called something like header_init and header_destroy.
For the init function I'd be a bit more careful. Check for a 0 argument of your pointer, and initialize your DS completely, something like *h = (http_header){ .name = name }. You never know if you or somebody will end up in adding another field to your structure. So by that at least all other fields are initialized with 0.
If you are new at C programming, you might perhaps want to use the Boehm's conservative garbage collector. Boehm's GC works very well in practice, and by using it systematically in your own code you could use GC_malloc instead of malloc and never bother about calling free or GC_free.
Hunting memory leaks in C (or even C++) code is often a headache. There are tools (like valgrind) which can help you, but you could decide to not bother by using Boehm's GC.
Garbage collection (and memory management) is a global property of a program, so if you use Boehm's GC you should decide that early.
The general solution to your problem is that of object ownership, as others have suggested. The simplest solution to your particular problem is, however, to use a char array for value, i.e., char value[12]. 2^32 has 10 decimal digits, +1 for the sign, +1 for the null-terminator.
You should ensure that 1) int is not larger than 32-bits at compile-time, 2) ensure that the value is within some acceptable range (HTTP codes have only 3 digits) before calling sprintf, 3) use snprintf.
So by using a static array you get rid of the ownership problem, AND you use less memory.

Need dynamically allocated (initialized) static variable

I need a static string(equivalent) variable in C and I'm having troubles implementing something like that.
I need to add content to that string every time the function is called. I tried with
static char *result = (char*)calloc(0, sizeof(char));
But that way I got:
error: initializer element is not
constant
Which makes sense, but I really don't know how to do this differently (tried with global variable also, but no success).
Anyone can help?
static initializers must be constant, as your error message indicates.
Assign it NULL, then in some other function, test if it's NULL, allocate the resources it needs (some sensible default) and go from there. Ensure you do clean up after you're done, and if this is a threaded environment, I suggest you go a different route put this in other storage that you pass along wherever you need it.
If you need to increase array length, use realloc instead.
char *buf = NULL;
while(/* some loop here */){
buf = realloc(buf, sizeof(/* new content */));
... // copy your new content to buf here
}
If you only add content, maybe better to use lists instead?
The most common way I've seen of doing this is to initialize a pointer to NULL, and store a length- optionally an end pointer is stored as well. When the function is called, check to see if you have enough space in your buffer available, and if not then realloc the memory chunk. Usually you don't want to realloc every time, and instead grow by either some fixed amount (usually selected based on the memory alignment of the system), or else to double the previous size (be sure to make sure you actually have enough free space!).
#define MYDATA_GROW_AMOUNT (12345) //exploit memory alignment on your system
...
/* if the compiler supports it, consider using __thread__ here */
static /* __thread__ */ char *mydata = NULL;
static /* __thread__ */ char *mydata_end = NULL;
static /* __thread__ */ size_t mydata_len = 0;
...
/* gcc? you might want to use
if(__builtin_expect((mydata_len < required_data_len),0))
here instead */
if(mydata_len < required_data_len)
{
mydata_end = mydata + mydata_len;
mydata_len += MYDATA_GROW_AMOUNT;
mydata = realloc(mydata,mydata_len);
}
...
I was able to get this to work for a "fixed" size array, i.e. the length can be defined during run-time, NOT compile time. I created a function which has the empty pointer itself A as an input, then alters it within and also returns it. The length len is custom run-time length:
char *malloc_char_array(char* &A, int len);
Then call that function in the array initialization:
static char *result = malloc_char_array(result, 50); //test length of 50
The static initialization only occurs the very first time the function is called, so it works great for arrays that need to be dynamic in size (i.e. not defined during compile time), yet still remain fixed throughout the entire run of the program.
And the allocating function would look something like:
char *malloc_char_array(char* &A, int len)
{
A = (char*) malloc(len * sizeof(char));
return A;
}
With this method there's no need to free the "static" allocated memory, just let it stay in the stack until the program quits.

char* as an argument to a function in C

When passing a char* as an argument to a function, should the called function do a free on that string? Otherwise the data would be "lost" right and the program would leak data. Or are char* handled in a special way by the compiler to avoid everyone from having to do free all the time and automatically deletes it one it goes out of scope? I pass "the string" to the function so not an instance to an already existing char*. Or should one use char[] instead? Just feels so dumb to set a fixed limit to the argument input.
Keep this simple principle in mind: "always free memory at the same level that you allocated it". In other words a function should never try to free memory that it itself has not allocated. A short example to clarify this:
#include "graphics.h"
// The graphics API will get a Canvas object for us. This may be newly allocated
// or one from a pool of pre-allocated objects.
Canvas* canvas = graphics_get_canvas ();
// If draw_image () frees canvas, that violates the above principle.
// The behavior of the program will be unspecified. So, just draw the image
// and return.
draw_image (canvas);
// This is also a violation.
// free (canvas) ;
// The right thing to do is to give back the Canvas object to the graphics API
// so that it is freed at the same 'level' where it was allocated.
graphics_return_canvas (canvas);
Note that the function is not named graphics_free_canvas () or something like that, because the API may choose to free it or reuse it by returning it to a pool. The point is, it is an extremely bad programming practice to assume ownership of a resource that we did not create, unless we are specifically told otherwise.
It sounds like you're asking about this usage:
void foo(char* str);
foo("test string");
This is a special case; "test string" is a constant string stored in the string table within the executable, and doesn't need to be freed. foo should actually take a const char* to illustrate that, and allowing string literals to be stored in non-constant char*s is deprecated in C++
Whether the function should do a free or not depends on who owns the string. This code is perfectly valid and doesn't result in any memory leak:
int main()
{
char* s = malloc(.....);
f(s);
free(s);
}
The free can be performed inside function f as well if it takes the ownership of the string. However note that it is dangerous since you are assuming that string passed to function f is always allocated on heap using malloc or related functions. If a user passes pointer to a string allocated on stack your program will behave unpredicably.
On a general note, compiler doesn't do any special handling for memory management of strings. From compiler's point of view it is just a bunch of characters.
It seems that you are used to OOP style. I don't like the OOP, and for me it would be weird if I'd obtain a copy of an object after assigning. In this case the string is somewhere in memory, and its address is sent as char*, and not the whole string.
Also, be careful that you can free() only the pointers returned by malloc(), and only once.
Sometime a API expects a allocated buffer and its upto to the owner of the function which calls that api to free it.
myFunc()
{
char *error = malloc(<max size of error string>);
foo(error);
//Free the pointer here
free(error);
}
Some API like GLIB api's expect pointer to address of a declared variable
myFunc()
{
GError *error;
glib_api(&error);
if (error)
{
printf("Error %s", error-> message);
// can use glib API to free if error is NON NULL but message is allocated by GLIB API
g_error_free(error);
}
}
So even if you have not allocated memory to a variable you need to do the freeing while using standard libraries.
An allocated piece of memory, if not freed will result in lesser memory in a multiprocess environment, thereby degrading the performance of the system.
With plain char *, I would recommend always writing code with a policy that the caller "owns" the string and is responsible for freeing it if it was obtained by malloc. On the other hand, one could certainly envision "pseudo-pass by value" string objects in C, implemented as a struct, where policy dictates you have to relinquish ownership of a string (or duplicate it first and pass the duplicate) when passing strings as arguments. This could work especially well if the implementation used reference-counted storage for strings where the object passed was just a reference to the storage, so that the "duplicate" operation would merely be a reference-count increment plus trivial wrapper-struct allocation (or even pass-by-value struct).
The pointer to char as a function variable is an address to the same variable except where it's been substituted as a constant string. Your question can't be explained with a simple yes/no guideline; it depends on context. In the code below, a struct allocated on heap and stack individually are passed by reference as well as a string char * and data is inserted into the struct. Notice how the mallocs differ as to when they are used but the function works all the same.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
// struct with all data within
typedef struct d
{
int number;
char name[50];
}data;
// struct with dynamic char *
typedef struct d2
{
int number;
char *name;
}dynamic_data;
// generic function placing data into struct
void InsertData ( data * out, int a, char * b )
{
out->number = a;
strcpy(out->name, b);
}
// generic function placing data into second struct
void InsertData2 ( dynamic_data * out, int a, char * b )
{
out->number = a;
strcpy(out->name, b);
}
int main ( void )
{
char * text = "some string\0";
int n = 20;
// allocated struct
data stuff;
dynamic_data stuff2;
dynamic_data * stuff3;
// need to allocate pointer within struct only
stuff2.name = (char *) malloc(50 * sizeof(char));
// heap allocated struct
stuff3 = (dynamic_data * ) malloc(50 * sizeof(dynamic_data));
// heap allocated sub element char *
stuff3->name = (char *) malloc(50 * sizeof(char));
// this is the data
printf ( "Pre insertion data\n" );
printf ( "s=[%s]\n", text );
printf ( "n=%d\n", n );
// this is the function insertting
InsertData ( &stuff, n, text );
printf ( "Post insertion data\n" );
printf ( "stuff.name=[%s]\n", stuff.name );
printf ( "stuff.number=%d\n", stuff.number );
// this is the function inserting
InsertData2 ( &stuff2, n, text );
printf ( "Post insertion data\n" );
printf ( "stuff.name=[%s]\n", stuff2.name );
printf ( "stuff.number=%d\n", stuff2.number );
//
// This is the segfault version - if nothing was allocated for pointers into
// this function scope, it would crash
// this is the function insertting under a heap allocated
InsertData2 ( stuff3, n, text );
printf ( "Post insertion data - dynamic version\n" );
printf ( "stuff3->name=[%s]\n", stuff3->name );
printf ( "stuff3->number=%d\n", stuff3->number );
// free in reverse order
free(stuff3->name);
free(stuff3);
free(stuff2.name);
return 0;
}

Resources