C - Not getting the right value with an argument pointer - c

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.

Related

return a modified array of char**

C- language——-Trying to call a function "test" from main(). This takes 3 arguments argc, argv and a pointer function which either turns the string into lower case or upper case. Then using the array of modified values i will just loop and print them.
I get segmentation fault error.
I want to return the entire array. So that in my main() i will loop through it and print it. How can i do this? Where am i going wrong in my code? Any help would be great.
Your codes have some incorrect points and are redundant as well.
You can try the below codes
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
char **test(int argc, const char *const *argv, int (*const chnge)(int)){
char **retArr = malloc((argc+1) * sizeof(char*));
for (int i = 0; i < argc; ++i) {
const char *str = argv[i];
int len = strlen(str);
char* transform = malloc((len+1) * sizeof(char));
for (int j = 0; j < (len+1); ++j) {
transform[j] = chnge(str[j]);
}
retArr[i] = transform;
}
retArr[argc] = NULL; // An array of char* terminated by NULL
return retArr;
}
int main(int argc, const char *const *argv) {
char **val1 = test(argc, argv, &toupper);
char **val2 = test(argc, argv, &tolower);
for (char *const *p = val1, *const *q = val2; *p && *q; ++argv, ++p, ++q) {
printf("[%s] -> [%s] [%s]\n", *argv, *p, *q);
free(*p);
free(*q);
}
free(val1);
free(val2);
}
I believe the answer may have to do with the fact that you are trying to directly act on a string 1. without using strcpy, and 2. using a pointer array (char*) instead of an array object (char[]) which can cause a segfault.
Sorry, this would better be suited to a comment and not an answer, but I unfortunately can't comment quite yet. This may be of help?

Give Pointer from Library

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

How to check if a pointer has been freed

I am a beginner in C. Below is my scenario - I have created a pointer variable in main function and it has been passed on to several functions(in this example 2 levels). And one of the functions frees it up. Now I need to have check in Main to see whether the pointer is freed or not, that means i need to setup the value of &str in main() to point to NULL. Not sure my approach is right here. Any help would be much appreciated
void func2(char *str)
{
free(str);
}
void func1(char *str)
{
func2(str);
}
int main()
{
char *str;
str=(char *) malloc(10);
func1(str);
if(str){ do something; } // if condition to check whether str is freed
}
#include <stdio.h>
#include <stdlib.h>
func2(char **str)
{
free(*str); //free
*str = NULL; //Set to NULL
}
func1(char **str) //func1 receives as **
{
func2(str); //Pass pointer to func2()
}
int main()
{
char *str = NULL;
str=(char *) malloc(10);
func1(&str); //Pass Address of pointer to func1()
if(str) //Check for NULL
{
printf("\n Not - Freed...\n");
}
else
{
printf("\n Freed...\n");
}
return 0;
}
In C all are pass by value. I suggest to study http://www.cs.fsu.edu/~myers/cgs4406/notes/pointers.html for understanding of this.
You could try something like this - first redefine malloc and free (track.h)
#ifndef track_h
#define track_h
extern void* trackmalloc(size_t size);
extern void trackfree(void* array);
extern void trackismalloc(void* array);
#define malloc trackmalloc
#define free trackfree
#endif
Then for every piece of code that uses malloc and free, replace #include with #include "track.h"
#include <stdlib.h>
#include <stdio.h>
#include "track.h" /* was <malloc.h> */
// A function which has a 20% chance of freeing the pointer
void twentypercent(char* array)
{
if (rand() < (RAND_MAX / 5))
free(array);
}
int main(int argc, char* argv[])
{
char* list = malloc(256);
int ii;
for (ii = 0; ii < 10; ++ii)
twentypercent(list);
if (trackismalloc(list)
printf("Not freed yet");
return 0;
}
Now define track.c. This will only free memory that has been allocated by by trackmalloc. If it was not allocated by trackmalloc, then it will report that the memory has already been freed.
#include <stdio.h>
#include <malloc.h>
#define TRACKER_MAX 2048
static void* tracker[TRACKER_MAX] = { 0 };
static int track_last = -1;
void* trackmalloc(size_t size)
{
// For simplicity, tracker will not be reused
tracker[++track_last] = malloc(size);
return tracker[track_last];
}
void trackfree(void* array)
{
// This will slow down as the list gets filled up.
// You will need a more efficient way of searching lists (possibly bsearch)
int tt;
for (tt = 0; tt < track_last; ++tt)
{
if (array == tracker[tt])
{
free(tracker[tt]);
tracker[tt] = 0;
break;
}
}
if (tt == track_last)
printf("%p already freed\n", array);
}
int trackismalloc(void* array)
{
// This will slow down as the list gets filled up.
// You will need a more efficient way of searching lists (possibly bsearch)
int tt, result = 0;
for (tt = 0; tt < track_last; ++tt)
{
if (array == tracker[tt])
{
result = 1;
break;
}
}
return result;
}
void func1(char** str) {
free(*str);
*str = NULL;
}
void func2(char** str) {
free(*str);
*str = NULL;
}
int main() {
char *str;
str = (char*) malloc(10);
func1(&str);
if (str) {
do something;
}
}
void func2(char **str)
{
free(*str);
*str = 0;
}
void func1(char **str)
{
func2(str);
}
int main()
{
char *str;
// I'd recommend using sizeof(type_you_want) * amount_of_elements instead of
// a constant number: -> malloc(sizeof(char) * 10);
str=(char *) malloc(10);
func1(&str); // You must pass the address of the pointer, because you want
// to change "WHAT IT POINTS TO", not "WHAT IS POINTED BY IT"
if(str){ do something; } // if condition to check whether str is freed
}
When you call a function in C, you pass a copy of those arguments, so you are passing a copy of that pointer (that copy still points to the same place, so you can change that place that it points to) but you want to change the pointer value, so you need to pass its address.
I have explained a little bit how pointers inside functions can be used in here
#include <stdio.h>
#include <stdlib.h>
void func2(char **str)
{
printf("%d %s\n",__LINE__,__func__);
free(*str);
*str = NULL;
}
void func1(char **str)
{
printf("%d %s\n",__LINE__,__func__);
func2(str);
}
char * allocaMem(char **ptr)
{
*ptr=(char *) malloc(sizeof(char)* 10);
if(!*ptr)
{
perror("");
}
else
{
return *ptr;
}
}
int main()
{
char *str = allocaMem(&str);
if (!str) {
printf("Error in malloc()\n");
return -1;
}
func1(&str);
if (str) {
printf("Memory Not freed\n");
} else {
printf("Memory freed\n");
}
}

How to convert a character to string using a function that has character as argument and returns string?

I had problem while using a function to do the task.Do I need to pass a pointer to character as well to do the task.I used the following code
#include <stdio.h>
char* change(char c)
{
char s[2];
s[0]=c;
s[1]='\0';
return s;
}
int main()
{
char t='o';
char* kk;
kk=change(t);
printf("\n%s",kk);
return 0;
}
Thanks
You cannot return a pointer to a local variable from a function without making a copy. Two ways of doing what you need in C are
Asking the caller to provide a buffer for writing the string, and returning the length, and
Allocating the return value dynamically with malloc or an equivalent, and requiring the caller to free the resultant string.
Here is the first approach:
int change(char c, char* res, int len) {
if (len < 2) return -1; // Invalid parameters
res[0]=c;
res[1]='\0';
return 1;
}
Here is the second approach:
char* change(char c) {
char *res = malloc(2);
res[0]=c;
res[1]='\0';
return res;
}
#include <stdio.h>
#include <stdlib.h>
char* change1(char c){
static char s[2];
s[0]=c;
return s;
}
char* change2(char c){
char *s = malloc(2);
s[0]=c;
s[1]='\0';
return s;
}
char* change3(char c, char *s){
s[0]=c;
s[1]='\0';
return s;
}
int main() {
char t='o';
char* kk;
kk=change1(t);
printf("%s\n", kk);
kk=change2(t);
printf("%s\n", kk);
free(kk);
char s[2];
kk = change3(t, s);
printf("%s\n", kk);
return 0;
}
You can just change
char s[2];
to
char *s; s = malloc(2);
and your program should work fine.

Splitting string with delimiters in C - segmentation fault

I want to write a function that will split a string into a char array. I know that the result array will ALWAYS have only two elements - servername and serverport. I wrote this, but it gives me "Segmentation fault" after compilation:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* splitString(char stringToSplit[])
{
int i = 0;
char serverinfo[2];
char *tmp;
tmp = strtok(stringToSplit, ":");
while (tmp != NULL)
{
serverinfo[i] = tmp;
tmp = strtok(NULL, ":");
i++;
}
return serverinfo;
}
int main(int argc, char **argv)
{
char st[] = "servername:1234";
char *tab = splitString(st);
printf("%s\n", tab[0]);
printf("%s\n", tab[1]);
return 0;
}
char serverinfo[2];
allocates space for two chars, but you store char*s there, so make it
char* serverinfo[2];
But you return it from the function, however, the local variable doesn't exist anymore after the function returned, so you need to malloc it
char **serverinfo = malloc(2*sizeof *serverinfo);
and declare the function as
char **splitString(char stringToSplit[])
for the correct type.

Resources