Give Pointer from Library - c

Ii've a big Problem. I write a static Library, what I would like to use in a Software. My Problem is: if you give a pointer from a function out of the library back to the main program the pointer have not the value from the pointer in the Library. Is there an issue, if you give pointer from an Libay.a back to the main.c
Main.c:
#include <stdio.h>
int main(int argc, const char * argv[]) {
char *ptr;
Prallow_its(ptr, 122);
printf("%s", ptr);
return 0;
}
Prallow.c from Prallow.a
[...]
char *Prallow_its(char *ptr, int i){
static char buffer[255];
sprintf(buffer, "%u", i);
ptr = buffer;
return ptr;
}
[...]

It's fine to return the pointer to your static buffer from the library. It lives in the same address space as the rest of your program. Of course, it's not thread-safe but that's a separate issue.
The real problem is the way you are calling it:
char *ptr; // <-- ptr uninitialised
Prallow_its(ptr, 122); // <-- return value ignored
printf("%c", ptr); // <-- ptr still uninitialised
You should instead do this:
ptr = Prallow_its( ptr, 122 );
Alternatively, you could allow ptr to be modified by Prallow_its. In that case, it must be defined like this:
char *Prallow_its( char **ptr, int i )
{
static char buffer[255];
sprintf(buffer, "%u", i);
*ptr = buffer;
return *ptr;
}
And called like this:
Prallow_its( &ptr, 122 );

C passes by value, so the line ptr = buffer in the library function does not change the value of ptr in main.
Also, the library function doesn't do anything with the pointer that's passed in, so there's no reason to pass the pointer. The code in Main.c should be
int main(int argc, const char * argv[])
{
char *ptr = Prallow_its(122);
printf("%s", ptr);
return 0;
}
and the code in Prallow.c should be
char *Prallow_its(int i)
{
static char buffer[255];
sprintf(buffer, "%u", i);
return buffer;
}

Related

function returns address of local variable [-Wreturn-local-addr] sprintf

i ma new c and i am trying sprintf along with pointers. all i get in console is return buf; as is please help me with this code.
#include <stdio.h>
char* stringa(char* str);
int main()
{
char* ss = "123";
stringa(ss);
return 0;
}
char* stringa( char* str)
{
char buf [100] ;
sprintf(buf,"hello %s", str);
return buf;
}
i tried many other ways too like sprintf_c and my computer shut down for serious. i am learning c.
Maybe this is what you want
#include <stdio.h>
char* stringa(char* dest, char* src)
int main()
{
char buf [100] ;
char* ss = "123";
printf("%s\n", stringa(buf, ss));
return 0;
}
char* stringa(char* dest, char* src)
{
sprintf(dest,"hello %s", src);
return dest;
}
In function 'char* stringa(char* str)' you are not allocating space in the heep for the char array 'buf' you are allocating space on the stack for that variable. (meaning after the function finishes, the variable 'buf' will be wiped away because it will be out of scope) therefore you must ask the compiler to allocate space in memory for this array, I recommend using malloc()
ex:
char* stringa( char* str)
{
char *buf = (char*)malloc(sizeof(char) * 100);
sprintf(buf,"hello %s", str);
return buf;
}
char* stringa( char* str)
{
char buf [100] ;
sprintf(buf,"hello %s", str);
return buf;
}
The problem with this code is that the buf char array is local to the stringa function. When the function returns, the memory occupied by the buf array is not valid anymore (for example, it could be reused later to store the content of other variables, arrays, etc.).
So when the function returns, you are giving the caller a pointer to garbage memory, to invalid data. The C compiler is trying to help you with that warning message; it's telling you: "Sorry, you are trying to pass back to the caller the address of a local variable (i.e. the buf char array) that is not valid anymore when the function terminates."
To fix this problem one option could be to allocate the char array for the output string at the call site, and let the invoked stringa function write into the caller-provided array:
#include <stdio.h>
char* stringa(char* dest, const char* str);
int main()
{
const char* ss = "123";
char buf[100];
stringa(buf, ss);
return 0;
}
/* Write the final message into 'dest'.
* Return the same dest address.
*/
char* stringa(char* dest, const char* str)
{
/* Note: better using a safe string function
* to prevent buffer overflows (e.g. sprintf_s),
* passing the maximum destination array size as well.
*/
sprintf(dest,"hello %s", str);
return dest;
}
Note that I also added some consts in your code to enforce some const-correctness for read-only input strings.

Return memory address as out parameter in function

I need to store the memory address of a string in an int pointer out parameter. I've created the code below to test the implementation.
void getMemAddress (int *a) {
char str[80] = "Hello world";
a = (int*)&str; // Assign memory address of str to a
printf("%s", (char*)a);
}
int main(int argc, const char * argv[]) {
int *memaddress;
getMemAddress(memaddress);
printf("%s", (char*)memaddress);
return 0;
}
printf("%s", (char*)a);
prints "Hello World" as it should but
printf("%s", (char*)memaddress);
prints null
How could I go about retrieving the actual memory address as using it to access the original string?
Thanks!
Parameters are passed by value in C. Similar issues have been answered countless times on stackoverflow.
You need this:
void getMemAddress (int **a) {
char str[80] = "Hello world";
*a = (int*)str; // Assign memory address of str to *a
printf("%s", (char*)*a);
}
int main(int argc, const char * argv[]) {
int *memaddress;
getMemAddress(&memaddress);
printf("%s", memaddress);
return 0;
}
Casting a memory address to int won't work on a 64 bit system. On a 32 bit system it works, but it's not very clean.
Other problem. You are returning the address of a local variable that is on the stack. As soon as you leave the getMemAddress function the str buffer will be overwritten by following function calls (also a classic problem). Never return the address of a local variable.
You are assining the address of &str to your function-local copy of the pointer a. What you need is to modify getMemAddress so that it takes int **a as an argument, and assign it like this:
*a = (int *) str;
then in main:
int *memaddress;
getMemAddress(&memaddress);
And one more thing-- str only exists inside your function. Once you exit the function, you won't be able to access it. To fix this, make str a char pointer and use malloc to allocate some memory for it. Then use strcpy to insert your string.
To modify something in a function, you need to pass a pointer to the thing you want to modify.
In this case you want to modify a pointer, so you need to pass a pointer to the pointer.
void getMemAddress (int **a) { // <-------------- added a *
char str[80] = "Hello world";
*a = (int*)str; // <-------------- added a *
printf("%s", (char*)*a); // <-------------- added a *
}
int main(int argc, const char * argv[]) {
int *memaddress;
getMemAddress(&memaddress); // <-------------- added a &
printf("%s", (char*)memaddress);
return 0;
}
Also, &str should be &str[0] or just str.
Also, str is a local variable, so it will cease to exist once getMemAddress returns (and then the printf call in main will probably print garbage). You could make str static, or you could return a pointer to a string literal instead (char *str = "Hello world"; *a = (int*)str;).

strcpy with destination pointer and return value

My plain C is a bit rusty, and I currently try to figure out why the first works and the second doesn't.
char *returnSomething(void) {
char *s = (char *) malloc(5 + 1);
strcpy(s, "Hello");
return s;
}
void dontReturnSomething(char *dest) {
char *s = (char *) malloc (5 + 1);
strcpy(s, "Hello");
dest = malloc(strlen(s) + 1);
strcpy(dest, s);
free(s);
}
int main(int argc, char *argv[]) {
char *first = returnSomething();
char *second = NULL;
dontReturnSomething(second);
printf("first: %s | second: %s", first, second);
}
Isn't it basically doing the same thing?
To return a pointer through a parameter you need a pointer to a pointer. Declare dest as char **dest.
void dontReturnSomething(char **dest) {
char *str = "Hello";
*dest = malloc(strlen(str) + 1);
strcpy(*dest, str);
}
Call the function like this:
dontReturnSomething(&second); // pass in address of second
To be more accurate, pointers to pointers are only necessary so long as, just as in the examples above, the memory is not allocated until after you enter the function. Just wanted to say this for anyone having pointer problems and thinks any passing of pointers always requires pointers to pointers to be passed.
For example, the below example works just fine.
void dontReturnSomething(int* testint)
{
int test = 33;
*testint = test;
}
int main(int argc, char *argv[])
{
int *first = calloc(1,sizeof(int));
printf("Before: %d\n", *first);
dontReturnSomething(first);
printf("After: %d\n", *first);
return(1);
}
If you run it, you'll get 0 and 33 as expected. Of course the caveat to this is that you absolutely have to have memory allocated to the pointer being used. If you allocated memory for the pointer inside the function, then you will be assigning it a new address that would then have to be returned so that the address can persist. The below example also works just fine.
void dontReturnSomething(char* testchar)
{
char* test = "Hello World!";
strcpy(testchar,test);
}
int main(int argc, char *argv[])
{
char *hello = NULL;
hello = calloc(13, sizeof(char));
printf("Before: %s\n", hello);
dontReturnSomething(hello);
printf("After: %s\n", hello);
return(1);
}
Of course you will pretty much never know the size of a string, or more usually a buffer, ahead of time. I just think it's important to understand the subtleties of pointers.

Trouble freeing memory in C with other functions

I'm creating a program where a struct is created through this process:
TokenizerT *TKCreate(char *separators, char *ts) {
TokenizerT * inu = malloc(sizeof(*inu));
char * sts = malloc(strlen(ts)*sizeof(char));
char * by = malloc(lim*sizeof(char));
strcpy(by, yr);
strcpy(sts, ts);
inu->sep = by;
inu->toks = sts;
return inu;
}
I need to free the struct inu through another function, but my function below only seems to free up the memory associated with TokenizerT.sep
void TKDestroy(TokenizerT *tk) {
free(tk->sep);
free(tk->toks);
}
How do I free up tk.sep and tk.toks?
EDIT: free(tk) results in this error: "malloc: * error for object 0x7fff55662bd8: pointer being freed was not allocated
* set a breakpoint in malloc_error_break to debug"
EDIT2: Struct definition
struct TokenizerT_ {
char * sep;
char * toks;
};
And
void TKDestroy(TokenizerT *tk) {
free(tk->sep);
free(tk->toks);
free(tk);
}
results in the same error specified in EDIT 1
EDIT 3: I've also added my main method:
int main(int argc, char **argv) {
char * arr = argv[1];
char * y = argv[2];
TokenizerT jer = *TKCreate(arr, y);
TKDestroy(&jer);
return 0;
}
First of all, the malloc of "inu" seems not correct
TokenizerT * inu = malloc(sizeof(inu));
I believe it only get memory with 4 bytes (in 32-bit system)
It should be:
TokenizerT * inu = malloc(sizeof(TokenizerT ));
And as you mentioned -- "I need to free the struct inu"
I think the allocated "inu" is passed into "TKDestroy(TokenizerT *tk)"
then:
void TKDestroy(TokenizerT *tk) {
free(tk->sep);
free(tk->toks);
free(tk) // this free is what you want to free "inu"
You just need to reverse the operations you did for allocation:
void TKDestroy(TokenizerT *tk) {
free(tk->sep); // for the 3rd malloc()
free(tk->toks); // for the 2nd malloc()
free(tk); // for the 1st malloc()
}
BTW: you know that sizeof(char) is always 1 - per definition?
The error you get results from your wrong allocation of tk - you just allocated enough memory for a pointer, not for the whole struct. That will mess things up.
Concerning your main, replace:
TokenizerT jer = *TKCreate(arr, y);
TKDestroy(&jer);
With:
TokenizerT *jer = TKCreate(arr, y);
TKDestroy(jer);
The reason being that your create-function returns a pointer, which you then pass to your destroy-function...
The reason that your code fails with that error is that &jer is the address of a local variable. It is the not address returned by the call to malloc.
TokenizerT jer = *TKCreate(arr, y);
TKDestroy(&jer);
So, jer is a local variable. The address returned by TKCreate is immediately de-referenced, and a copy of the struct is made. You simply fail to retain the address returned by TKCreate and it is leaked. Then when you attempt to call free on &jer, the address of a local variable, your environment correctly reports that you are passing to free an address that was not created by a call to malloc.
As I said in your previous question, it makes a lot more sense to return the struct by value than using dynamic allocation. On top of that, your string allocations are incorrectly performed. You must always allocate sufficient room for the null-terminator.
I would write your program like this:
#include <stdlib.h>
#include <string.h>
typedef struct {
char *sep;
char *toks;
} TokenizerT;
TokenizerT TKCreate(const char *seps, const char *toks)
{
TokenizerT inu;
inu.sep = malloc(strlen(seps)+1);
strcpy(inu.sep, seps);
inu.toks = malloc(strlen(toks)+1);
strcpy(inu.toks, toks);
return inu;
}
void TKDestroy(TokenizerT *tk)
{
free(tk->sep);
free(tk->toks);
}
int main(int argc, char **argv)
{
TokenizerT jer = TKCreate(argv[1], argv[2]);
TKDestroy(&jer);
return 0;
}
Notes:
By definition, sizeof(char) is 1 so idiom dictates that it is omitted as a multiplicative factor in calls to malloc().
I've given the parameters to TKCreate the same names as the fields of the struct. This makes it easier to understand what is going on. What's more, your code looked plain wrong since it was ignoring one of the parameters.
As stated above, the struct is returned by value. This is conceptually easier to handle.
You might prefer to write a helper function to duplicate strings. If your compiler's runtime already has a function named strdup you might use that. Otherwise you can use this trivial implementation:
char *strdup(const char *str)
{
char *result = malloc(strlen(str)+1);
strcpy(result, str);
return result;
}
If you only want to search for the null-terminator once you write it like this:
char *strdup(const char *str)
{
size_t len = strlen(str)+1;
char *result = malloc(len);
memcpy(result, str, len);
return result;
}
Then the code becomes:
#include <stdlib.h>
#include <string.h>
char *strdup(const char *str)
{
size_t len = strlen(str)+1;
char *result = malloc(len);
memcpy(result, str, len);
return result;
}
typedef struct {
char *sep;
char *toks;
} TokenizerT;
TokenizerT TKCreate(const char *seps, const char *toks)
{
TokenizerT inu;
inu.sep = strdup(seps);
inu.toks = strdup(toks);
return inu;
}
void TKDestroy(TokenizerT *tk)
{
free(tk->sep);
free(tk->toks);
}
int main(int argc, char **argv)
{
TokenizerT jer = TKCreate(argv[1], argv[2]);
TKDestroy(&jer);
return 0;
}
If you are desperate to return a pointer to the struct, do it like this:
#include <stdlib.h>
#include <string.h>
char *strdup(const char *str)
{
size_t len = strlen(str)+1;
char *result = malloc(len);
memcpy(result, str, len);
return result;
}
typedef struct {
char *sep;
char *toks;
} TokenizerT;
TokenizerT *TKCreate(const char *seps, const char *toks)
{
TokenizerT *inu = malloc(sizeof *inu);
inu->sep = strdup(seps);
inu->toks = strdup(toks);
return inu;
}
void TKDestroy(TokenizerT *tk)
{
free(tk->sep);
free(tk->toks);
free(tk);
}
int main(int argc, char **argv)
{
TokenizerT *jer = TKCreate(argv[1], argv[2]);
TKDestroy(jer);
return 0;
}
Note particularly the difference in the way I call TKCreate and TKDestroy.
Finally, I have ignored all error checking on the calls to malloc(). In real production code you would not do that, but for the sake of clarity of exposition it is much better to omit it here.

C - Not getting the right value with an argument pointer

The get_current_path function gets a pointer to a char string of the current working directory. printf("%s\n", buf); in the function itself prints exactly what I want, but then outside of the function, printf("%s", thisbuf); gives me a lot of garbage. I assume I've made some silly mistake here, but I can't figure out what it is.
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
int get_current_path(char *buf) {
long cwd_size;
char *ptr;
cwd_size = pathconf(".", _PC_PATH_MAX);
if ((buf = (char *) malloc((size_t) cwd_size)) != NULL)
ptr = getcwd(buf, (size_t)cwd_size);
else cwd_size == -1;
printf("%s\n", buf);
printf("%ld\n", cwd_size);
return cwd_size;
}
int main (int argc, char **argv)
{
char *thisbuf;
get_current_path(thisbuf);
printf("%s", thisbuf);
return 0;
}
You should pass a pointer to char *
int get_current_path(char **buf)
{
*buf = ...;
}
int main()
{
char *thisbuf;
get_current_path(&thisbuf);
}
Parameters in C are pass-by-value, which means that get_current_path can't change the value of "thisbuf" passed in by the caller.
To make the change, you would have to pass in a pointer to "thisbuf":
int get_current_path(char **resultBuf) {
char *buf = (char *) malloc((size_t) cwd_size);
...
*resultBuf = buf; // changes "thisbuf" in the caller
}
....
get_current_path(&thisbuf); // note - passing pointer to "thisbuf"
Try this instead:
int get_current_path(char **buf) {
*buf = something; // Set buf with indirection now.
And:
int main (int argc, char **argv)
{
char *thisbuf;
get_current_path(&thisbuf);
printf("%s", thisbuf);
return 0;
}
You were trying to pass a copy of buf to get_current_path, so when buf was modified, the original pointer to buf was not modified.

Resources