Dynamic array and functionalize malloc [duplicate] - c

This question already has an answer here:
Dynamic memory access only works inside function
(1 answer)
Closed 6 years ago.
I try to malloc an array functionally, and this function also can check whether the memory is enough or not.
The first code block can't work.
When it executes " *pi = 5 ", the compiler shows this error message " Thread 1: EXC_BAD_ACCESS(code=1, address=0x0) " .
#include <stdio.h>
#include <stdlib.h>
void malloc_and_check(int *var)
{
if(!(var = (int*)malloc(sizeof(int))))
{
fprintf(stderr, "Insufficient Memory\n");
exit(EXIT_FAILURE);
}
}
int main(int argc, const char * argv[])
{
int *pi;
malloc_and_check(pi);
*pi = 5;
printf("%d", *pi);
free(pi);
}
However, the codes as below can work normally.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, const char * argv[])
{
int *pi;
if(!(pi = (int*)malloc(sizeof(int))))
{
fprintf(stderr, "Insufficient Memory\n");
exit(EXIT_FAILURE);
}
*pi = 5;
printf("%d", *pi);
free(pi);
}
What are the difference between them? Thanks!

When you pass the int * var into malloc_and_check you are updating a local copy of the pointer so the original is unchanged. You can fix this in two ways:
(a) return the pointer from malloc_and_check
int * malloc_and_check()
{
int * var = 0;
if(!(var = (int*)malloc(sizeof(int))))
{
fprintf(stderr, "Insufficient Memory\n");
return 0;
}
return var;
}
Then you would call it as
pi = malloc_and_check();
(b) pass in a pointer to the pointer
void malloc_and_check(int ** var)
{
if(!( *var = (int*)malloc(sizeof(int))))
{
fprintf(stderr, "Insufficient Memory\n");
exit(EXIT_FAILURE);
}
}
Then you would pass it in as
malloc_and_check(&pi);

The pointer var is allocated memory dynamically but it is local to the function malloc_and_check. The pointer pi in the function main will not get to know the address of the memory allocated to var. It is a bad access and may also result in crash sometimes.
try the code below to get the expected results :
#include <stdio.h>
#include <stdlib.h>
void malloc_and_check(int **var)
{
int *var1;
if(!(var1 = (int*)malloc(sizeof(int))))
{
fprintf(stderr, "Insufficient Memory\n");
exit(EXIT_FAILURE);
}
else
*var = var1;
}
int main(int argc, const char * argv[])
{
int *pi;
malloc_and_check(&pi);
*pi = 5;
printf("%d", *pi);
free(pi);
}

You are trying to pass the pointer by value (pass by value). You need to pass a double pointer to the function malloc_and_check. Due to this the value assigned to the pointer is not reflecting back in the caller.
Please modify your code as below:
#include <stdio.h>
#include <stdlib.h>
void malloc_and_check(int **var)
{
if(!(*var = malloc(sizeof(int))))
{
fprintf(stderr, "Insufficient Memory\n");
exit(EXIT_FAILURE);
}
}
int main(int argc, const char * argv[])
{
int *pi;
malloc_and_check(&pi);
*pi = 5;
printf("%d", *pi);
free(pi);
}

The change you make to var in the function is lost when the function returns. Either you need to pass var as a double pointer or you need to return a pointer from the function.
Example where the function returns a pointer:
#include <stdio.h>
#include <stdlib.h>
int* malloc_and_check()
{
int *var;
if(!(var = malloc(sizeof(int))))
{
fprintf(stderr, "Insufficient Memory\n");
exit(EXIT_FAILURE);
}
return var;
}
int main(int argc, const char * argv[])
{
int *pi;
pi = malloc_and_check();
*pi = 5;
printf("%d", *pi);
free(pi);
}

Related

My C code does not work but another example, something similar to me, works. Why?

My code is not working... But another example that is similar to my code is working. How can I fix?
It seems like pthread_join() is internally change integer value like my code. But mine does not work.
Can anybody help me to fix?
#include <stdio.h>
void test(void **temp) {
int foo = 3;
*temp = foo;
}
int main(void) {
int temp;
test((void **)&temp);
printf("%d\n", temp);
return 0;
}
pthread_join example:
#include <pthread.h>
#include <stdlib.h>
void *test(void *data) {
int i;
int a = *(int *)data;
for (i = 0; i < 10; i++) {
printf("%d\n", i * a);
}
}
int main() {
int a = 100;
pthread_t thread_t;
int status;
if (pthread_create(&thread_t, NULL, test, (void *)&a) < 0) {
perror("thread create error:");
exit(0);
}
pthread_join(thread_t, (void **)&status);
printf("Thread End %d\n", status);
return 1;
}
But mine does not work..
This statement:
pthread_join(thread_t, (void **)&status);
assigns to status the return value of your thread function. But your function doesn't return anything, so you get garbage.
To fix this, make your test function return something.
P.S. Please do turn on compiler warnings (-Wall, -Wextra) -- the compiler should have warned you of the bug already.
P.P.S Please do not name your variables like this: thread_t -- the _t stands for type, and thead_t is not a type.
You are trying to make temp into two void pointers (void**) when you actually only have one pointer to the int temp. Just return the pointer value and you can use this in a similar pthread example.
#include <stdio.h>
#include <stdlib.h>
void *test(void *temp) {
int *ptr = (int*)malloc(sizeof(int));
*ptr = 3;
return ptr;
}
int main(int argc, char *argv[]) {
int *temp = (int*)test(nullptr);
printf("%d\n", *temp);
free(temp);
return 0;
}

How to pass 2d array of string to the function and print value of it?

Why it is not working... It should be working, right? gcc have problem with this line, but why?
render_history(history, 2);
Sorry for bothering. I am just a beginner.
#include <stdio.h>
void render_history(char** history, const int entry);
int main()
{
char* history[3][4];
history[0][0] = "1234";
history[1][0] = "5678";
history[2][0] = "9012";
render_history(history, 2); //??
return 0;
}
void render_history(char** history, const int entry)
{
// print "9012"
}
gcc have problem with this line, but why?
Because the type is wrong. char* history[3][4]; can't be passed as char**. They are incompatible types.
Try something like:
#include <stdio.h>
void render_history(char* (*history)[4] , const int entry)
{
printf("%s\n", history[entry][0]);
}
int main()
{
char* history[3][4];
history[0][0] = "1234";
history[1][0] = "5678";
history[2][0] = "9012";
render_history(history, 2);
return 0;
}
As mentioned above double pointer not equal to 2D array.
You can also use pointer to pointer of char. char **history. And with this you have several option:
1) Use compound literals
#include <stdio.h>
void render_history(const char **history, const int entry)
{
printf("%s\n", history[entry]);
}
int main(void)
{
const char **history = (const char *[]) { "1234", "5678", "9012", NULL};
render_history(history, 2);
return 0;
}
If you need change your data later
2) Use dynamic memory allocation with malloc
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void render_history(char **history, const int entry)
{
printf("%s\n", history[entry]);
}
int main(void)
{
char **history = malloc(3 * sizeof(char *));
for (int i = 0; i < 3; ++i)
{
history[i] = malloc(4 * sizeof(char));
}
strcpy(history[0], "1234");
strcpy(history[1], "5678");
strcpy(history[2], "9012");
history[3] = NULL;
render_history(history, 2);
return 0;
}
If you use 2nd option dont forget free memory after use.

How to assign a void** array (return value of a function) to a variable?

Needed: A function which returns two different values (int,str)
So foo calculates smth. and stores the addresses of the two values
in the return array.
Now I want to read the values back into variables of these types.
void** foo(){
void** bar = malloc(2 * sizeof(void*));
...
return bar;
}
int main(int argc, char* argv[]){
void** result = foo();
int* val1 = (int*)result[0];
char* val2 = (char*)result[1];
}
This snippet is not compiling.
Excuse me:
the problem was not the code but that I declared it in a case branch
without any compution instructions.
int main(int argc, char* argv[]){
switch(xyz){
case a:
void** result = foo();
int* val1 = (int*)result[0];
char* val2 = (char*)result[1];
break;
}
}
Which seems not to make sense in a case.
Thanks though.
If you come up with the need to use a void**, it is a strong indication of poor program design. Just forget about this idea. void pointers in general is something you should avoid.
What you actually want to do seems to be something like this:
typedef struct
{
int i;
char c;
} something_t;
something_t* foo (void)
{
something_t* result = malloc (sizeof(*result));
...
return result;
}
int main(int argc, char* argv[]){
something_t* result = foo();
int* val1 = &result->i;
char* val2 = &result->c;
}
If the struct members need to be pointers, simply change the struct.
You should use structure to do your job
#include <stdio.h>
#include <stdlib.h>
#define STRING_WIDTH 32
struct test
{
int val1;
char *val2;
};
struct test *foo(void)
{
struct test *bar = malloc(sizeof(struct test));
if (bar != NULL)
{
bar->val1 = 0;
bar->val2 = calloc (STRING_WIDTH, 1);
if (bar->val2 == NULL)
return NULL;
}
return bar;
}
int main( void )
{
struct test *result = foo();
if (result != NULL)
{
// USE YOUR STRUCT
}
return 0;
}
Take note that mallocated memory must be freed

Getting all functions with prefix in C

Is it possible to get function pointers to functions that have a prefix? At first I thought the names of c functions were lost during compilation. But then, dlsym returns the pointer to a function of a specified name.
So if there a way to do something like:
void * handle = dlopen(0, RTLD_NOW|RTLD_GLOBAL);
*(void **)(&fptr);
while(fptr = dlsym(handle, "prefix*")) {
fptr(args);
}
Why not just do something like this:
#include <stdio.h>
void funcA(int n) { printf("funcA: %d\n", n); }
void funcB(int n) { printf("funcB: %d\n", n); }
void funcC(int n) { printf("funcC: %d\n", n); }
void (*funcs[3]) (int n) = {
funcA,
funcB,
funcC
};
int main() {
int i;
for (i = 0; i < sizeof funcs / sizeof *funcs; ++i)
funcs[i](i);
return 0;
}
well this isn't a built-in way, and I don't think there is a built-in way... you could parse nm, but that is yucky.
but if you are building a plug in arch you can use an already known symbol to get all of the symbols.
lib.c
char ** functions()
{
static char * f[3] = {"function1","function2",NULL};
return f;
}
void function1()
{
printf("function1\n");
}
void function2()
{
printf("function2\n");
}
main.c
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
#include <errno.h>
typedef char ** (*functions)(void);
typedef void (*voidFunc)(void);
int main(int argc, const char * argv[])
{
void * ref = dlopen("/abs/path/to/libExample.dylib", RTLD_LAZY | RTLD_LOCAL);
if (!ref)
{
printf("filed to open dylib: %i",errno);
}
functions f = dlsym(ref, "functions");
if (f)
{
char** fnames = f();
char * fname = NULL;
for (int i = 0; 1 ; i++)
{
fname = fnames[i];
if (fname) {
voidFunc g = dlsym(ref, fname);
if (g)
{
g();
}
}else{
break;
}
}
}
dlclose(ref);
return EXIT_SUCCESS;
}
outputs:
function1
function2
Program ended with exit code: 0
not a linux way, but on OS X there is a some extra stuff that would probably be easier:
/*
* Structure filled in by dladdr().
*/
typedef struct dl_info {
const char *dli_fname; /* Pathname of shared object */
void *dli_fbase; /* Base address of shared object */
const char *dli_sname; /* Name of nearest symbol */
void *dli_saddr; /* Address of nearest symbol */
} Dl_info;
extern int dladdr(const void *, Dl_info *);

Wrong result when copying an array of strings

I have the following code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* user;
char* passwd;
int nr;
void test()
{
int i=0;
for(i=0;i<argc;i++)
printf("Hello %s \n",user);
}
int main(int argc,char*argv[])
{
int i;
nr=argc;
for (i=0; i<argc; i++)
{
user=strdup(argv[i]);
}
test();
return 0;
}
The result is the argv[argc] on all the positions. How can I fix this? I wwant to have that test() outside the loop.
**
EDIT
**
After the ANSWERS here this is my new code, which is not working. Can anyone say why?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* user;
void test(int n)
{
int i=0;
for(i=0;i<n;i++)
printf("%s \n",user[i]);
}
int main(int argc,char*argv[])
{
user = (char*) malloc(argc*sizeof(char));
int i;
for (i=0;i<argc;i++)
{
user[i]=argv[i];
}
test(argc);
return 0;
}
You are assigning to both password and user at each iteration of the for loop. The final values you see are from the last iteration. Also, there is memory leak due to overwriting the pointers from previous strdup calls. In fact, you do not need a loop:
int main(int argc,char*argv[])
{
if(argc == 3) {
user=strdup(argv[1]);
passwd=strdup(argv[2]);
} else {
// error: usage
}
test();
return 0;
}
If you want to have multiple user/password combinations:
char *user[256], *passwd[256];
void test(int n) {
int i;
for(i=0;i<n;i++)
printf("Hello %s \n",user[i]);
}
int main(int argc,char*argv[])
{
int i;
for(i = 0; i < argc && i < 256; i+=2) {
user[i]=strdup(argv[i]);
passwd[i]=strdup(argv[i+1]);
}
test(argc);
return 0;
}
Because you overwrite the pointers user and passwd in every iteration. Hence, you'll only see the last string.
If you can tell your aim of the program, a better answer can be provided. Because I am not sure whether you want to read one user and passwd Or an array of users and passwds.
After you edit, I see you want to read an array of strings:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char** user;
// or char *user[100]; /* If you want a fix length array of pointers. Now, you dont have to malloc. /*
char* passwd;
int nr;
void test(int argc)
{
int i=0;
for(i=0;i<argc;i++)
printf("Hello %s \n",user[i]);
}
int main(int argc,char*argv[])
{
int i;
nr=argc;
user = malloc(argc*sizeof(char*));
for (i=0; i<argc; i++)
{
user[i]=strdup(argv[i]);
}
test(argc);
return 0;
}
Of course; in test() you don't use i other than a loop variable and in main() you keep overwriting the previous value of user and passwd. In effect, what you do is:
user = strdup(argv[0]); /* Note: argv[0] is the program name. */
passwd = strdup(argv[0]);
user = strdup(argv[1]);
passwd = strdup(argv[1]);
user = strdup(argv[2]);
passwd = strdup(argv[2]);
user = strdup(argv[3]);
passwd = strdup(argv[3]);
printf("%s %s \n", user, passwd);
With this information, can you fix your program?
$ cat trash.c
#include <stdio.h>
#include <string.h>
void test(FILE* stream, char* usr, char* pass) {
fprintf( stream, "%s#%s\n", usr, pass);
}
int main(int argc, char** argv) {
int i = 1;
if (argc % 2) {
while(argv[i]) {
test(stdout, argv[i], argv[i + 1]);
i += 2;
}
}
return 0;
}
$ clang trash.c
$ ./a.out user1 pass1 user2 pass2
user1#pass1
user2#pass2
$
also if you call strdup() don't forget to free memory, because strdup called malloc().

Resources