passing a char array by reference in C - c

Hi I really can't get my head around this. I'm basically trying to return a char array from a function by passing the output array in as a parameter. Here is what I have so far:
The function:
int GetComputerName(char *name, char *ip_address){
*name = "testing";
return 0;
}
And calling it:
char comp_name[50];
GetComputerName(&comp_name, serverIP);
printf("\n\n name: %s\n\n", comp_name);
I have tried switching and swapping the * and & to see what will work and have read up on pointers and stuff yet what I think should be happening an what actually does happen is two very different things and now I think I have confused myself more than when I started!! lol
Can someone please help me out and explain what the correct way of doing this is?!
Thanks in advance =)

This line:
*name = "testing";
is invalid, as you assign the pointer to "testing" into a char pointed by name. You need to copy the data into the buffer. It should be:
int GetComputerName(char *name, char *ip_address){
strcpy(name,"testing");
return 0;
}
or even better (to avoid overflows):
int GetComputerName(char *name, size_t buff_len, char *ip_address){
strncpy(name,"testing", buff_len);
name[buff_len - 1] = '\0';
return 0;
}
And call it:
GetComputerName(comp_name, sizeof(comp_name), serverIP);

Related

correct way to filter execve environment

I'm trying to write a LD_PRELOADable library that prevents processes from removing itself from this variable (to make sure children inherit it).
So far I sucessfully wrapped putenv,setenv and clearenv, but execve gives me issues.
My code so far:
int (*real_execve)(const char *filename, char *const argv[], char *const envp[]);
int execve(const char *filename, char *const argv[], char *const envp[]){
real_execve = dlsym(RTLD_NEXT,"execve");
char *path = getenv("LD_PRELOAD");
fprintf(stderr, "INTERCEPTED execve, env:\n");
int i;
for(i=0;envp[i]!=NULL;i++);
char *nenvp[i+1];
nenvp[i]=NULL;
for(i=0;envp[i]!=NULL;i++){
char *string = envp[i];
char *buf = malloc((strlen(string)+1)*sizeof(char));
strcpy(buf,string);
char *name = strtok(buf,"=");
char *value = strtok(NULL,"=");
if(0==strcmp(name,"LD_PRELOAD")){
fprintf(stderr," FIXING '%s'\n",string);
char * nstring = malloc((strlen(name)+strlen(path)+strlen(value)+3)*sizeof(char));
strcpy(nstring,name);
strcat(nstring,"=");
strcat(nstring,path);
strcat(nstring,":");
strcat(nstring,value);
nenvp[i]=nstring;
fprintf(stderr," TO '%s'\n",nenvp[i]);
free(string);
}else{
nenvp[i]=envp[i];
fprintf(stderr," LEFT '%s'\n",nenvp[i]);
}
free(buf);
}
fprintf(stderr, " CALLING %s\n", filename);
return real_execve(filename,argv,nenvp);
}
I'm encountering 2 issues:
it logs things like:
FIXING 'LD_PRELOAD=/usr/$LIB/libstdc++.so.6 /usr/$LIB/libgcc_s.so.1 /usr/$LIB/libxcb.so.1'
TO 'LD_PRELOAD=/usr/$LIB/libstdc++.so.6 /usr/$LIB/libgcc_s.so.1 /usr/$LIB/libxcb.so.1:/usr/$LIB/libstdc++.so.6 /usr/$LIB/libgcc_s.so.1 /usr/$LIB/libxcb.so.1'
instead of the expected prepending of the path to self, so I guess I somehow messed up the strtok.
I get a lot of errors like those:
Error in 'sh': munmap_chunk(): invalid pointer: 0x00007fff3888af4a
which to me sounds like I'm freeing too much probably, but I can't find the culprit.
I hope this doesn't sound too much like a "hey fix this for me" post but I'm kinda hitting a wall here and any help would be very appreciated.
You cannot assume that an individual string in envp was allocated with malloc so free(string) could be Undefined Behaviour. It is virtually impossible to call exec* with a completely empty heap and the entire image will be replaced anyway, so it's not worth worrying about.
Your second strtok call should supply NULL as its first argument. See man strtok for an explanation and examples.
Do this straight forward:
Create a new pointer array with the size necessary to hold the new env/ var/s
strdup() all elements you need from the old to the new array.
Add new stuff as necessary.
Make sure the last pointer in the array is NULL.
Pass the new pointer array to the original execve().
Do not modify or even (try to) free() entries of the old environment.

Double dimension array, attribute value but can't read from it later

I'm passing values beteween childs and need to store some values to later use.
the definitions and use in functions
char fouts[MAX_SIZE][10];
the function where i give the array the values:
void connect(char *nodo, char *out[], int nouts) {
(...)
for(i=0;i<nouts;i++) {
fouts[fnum][i] = out[i];
}
(...)
and the function where i'm trying to use them:
void disconnect(char *nodo, char *remover){
char *outs[10];
nouts = fnouts[getfnum];
int m =0;
for(i=0;i<nouts;i++) {
if(strcmp(fouts[getfnum][i],nodo) != 0) { outs[m] = fouts[getfnum][i]; m++ ; }
}
no matter what i did to try to fixm everytime it tries to execute this last for, it gives a segmentation fault.
have tried somethings (read fouts[getfnum][0] for example directly and gives a segmentaton fault, but fouts[getfnum] gives "trash")
check the value after it been atributed fouts[fnum][i] = out[i]; here and it checks out, so i guess that part is ok).
don't know if its something obvious or not, but any help?
You are mixing char and char*.
fouts[fnum][i] is a char
and
out[i] is a char pointer
So in this line
fouts[fnum][i] = out[i];
you assign a char pointer to a char which is illegal.
And in this line
if(strcmp(fouts[getfnum][i],nodo) != 0)
you pass a char (i.e. fouts[getfnum][i]) to strcmp.
That is not legal as strcmp expects a char*
From the posted code, it is hard to tell how to fix the problems. Maybe you just need:
char* fouts[MAX_SIZE][10];

trying to make a function of 2 strings combined into a new one

Is the code fine? When I use puts(nstr) in the function I do get the right result , but when on main all I get is "riends" output.
using a Microsoft Visual C++ Express if it helps.
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<malloc.h>
char* strcpy2 (char* str1, char* str2)
{
char nstr[20];
int i,j;
for (i = 0; str1[i] != '\0'; i++)
{
nstr[i] = str1[i];
}
for (j = i, i = 0; str2[i]!='\0'; i++, j++)
{
nstr[j] = str2[i];
}
nstr[j] = '\0';
return nstr;
}
void main()
{
char str1[10] = "Hello";
char str2[10] = ",friends";
puts(strcpy2(str1, str2));
}
Summary
Welcome to SO. The main issue is that you're returning the address of a variable that has gone out of scope by the time you try to use it.
Detail
When functions are invoked, local variables are pushed onto a stack (not the data structure!). Here, your local nstr array variable is pushed and is said to be defined within the function's scope.
However, when functions return, local variables are destroyed along with the stack on which they were placed. This means that your nstr variable, has already gone out of scope by the time your function has returned.
This causes your caller, main in this case, to end up with an invalid reference to memory that is no longer in use by the program, which can trigger all sorts of bugs and crashes.
Instead, you should pass a 3rd argument to your function so that it serves as the place where the new concatenated string will go. I don't think making the variable static here is necessary or a good idea. There's no need to keep something in memory when it shouldn't be.
Updated Code
Based on this, your code should look more like this
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
void strcpy2 (char str1[], char str2[], char str3[])
{
// ...
}
int main(void)
{
char str1[10] = "Hello";
char str2[10] = ",friends";
char str3[20];
strcpy2(str1, str2, str3);
puts(str3);
return 0;
}
You should be able to take it from here.
Update - Why You Should Not Use static Here
Many have recommended using the static keyword here. I advice against this for the following reasons. Using static for your local variable causes your function to be:
Not Thread-Safe: static variables are shared variables;
Not Reusable: function breaks trying to use strings longer than your toy example with a cap of 19+1 chars including null and defeats the purpose of having a function in the first place;
Not Memory Efficient: the static variable will remain in memory with a string that no longer needs to be used until your program exits
You'd have a better-quality function if you pass the 3rd argument as a destination that already has enough space to contain the originals to be concatenated.
You could return a pointer that has been malloc'ed, but note that this is a bit more dangerous and will require more care from everyone using your function. For example, it must be unambiguously clear to every client that it's now their responsibility to free the memory returned by your function. This can be more error-prone because the mallocs are not immediately visible to those using it. (Forgot to free your function's internal/invisible malloc? Whoops! Hello memory leak!).
Using the 3rd param should be safer in general.
You should really take the time to understand the side-effects and consequences that follow from decisions like these.
nstr is local to function strcpy2. Returning pointer to automatic local variable invokes undefined behavior. Change it to
static char nstr[20];
or use malloc to allocate memory dynamically.
The way you're doing this will not work. For one thing your variable nstr is locally defined and it will not be any good after you exit the function. I could show you how, but I'm guessing you're a student and need to hit the books a little harder. You can do this, it ain't that hard.
I think a pointer with malloc will do the job here, try this:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
char *strcpy2 (char *str1, char *str2){
char *result;
size_t length = 0,i,j;
length = strlen(str1) + strlen(str2);
result = malloc(length + 1);
for (i = 0; str1[i] != '\0'; i++){
result[i] = str1[i];
}
for (j = i, i = 0; str2[i]!='\0'; i++, j++){
result[j] = str2[i];
}
result[j] = '\0';
return result;
}
int main(void){
char str1[10] = "Hello";
char str2[10] = ",friends";
char *res = strcpy2(str1, str2);
printf("%s\n",res);
free(res);
return 0;
}
Output:
Hello,friends
if you print it using printf("%s", strcpy2(str1, str2)); it will be fine.
I dont know whats wrong with puts

Pointers, Strings and functions in C

I've missed a week of class in which they covered pointers but I haven't been able to get the notes from class but my HW is due and I still don't understand how to use pointers to pass strings from function to function... below is my code in which I realize the pointers are beyond messed up but I've tried to read other forums but just get lost. Any help is appreciated.
#include <stdio.h>
char* returnInPlace(char);
int palindrom(char, char );
main(void)
{
char newString[20];
printf("Enter a string: ");
scanf("%s",&newString);
char flippedString[20]=reverseInPlace(newString);
int palCheck= palindrome(newString, flippedString);
if (palCheck==0)
printf("\n\tThe reverse string is %s, so we don't have a palindrome.", flippedString);
else
printf("\n\tThe reverse string is %s, so we do have a palindrome.", flippedString);
}
char* reverseInPlace(char newString)
{
int iterator;
char flipped[20];
char *ptr1;
for(iterator=0;iterator<20;iterator++)
{
flipped[iterator]=firstString[19-iterator];
}
ptr1=flipped[];
return *ptr1;
}
int palindrome(char newString, char flippedString)
{
int iterator;
int palCheck=1;
for(iterator=0;iterator<20;iterator++)
{
if (firstString[iterator]==secondString[iterator])
continue;
else
{
palCheck=0;
break;
}
}
return palCheck;
}
Problem 1
In char* reverseInPlace(char newString), you're using
return *ptr1;
which is wrong. What you may want is
return ptr1;
Problem 2
ptr1=flipped[];
is wrong. Here, you're assigning the base address of a local variable flipped and returning that value. flipped will cease to exist after reverseInPlace() finishes execution. You need to use dynamic memory allocation.
Problem 3
char flippedString[20]=reverseInPlace(newString);
is wrong. You cannot assign an array with = unless as initialization at time of definition.
Problem 4
char* reverseInPlace(char newString)
this function definition looks wrong by seeing the way it is being called. Maybe what you want is
char* reverseInPlace(char* newString)
instead.
......and maybe many more. Strongly suggest to read some good book about Pointers and C basics before jumping into writing code.

Declaring an array of character pointers (arg passing)

This is something that should be easy to answer, but is more difficult for me to find a particular right answer on Google or in K&R. I could totally be overlooking this, too, and if so please set me straight!
The pertinent code is below:
int main(){
char tokens[100][100];
char *str = "This is my string";
tokenize(str, tokens);
for(int i = 0; i < 100; i++){
printf("%s is a token\n", tokens[i]);
}
}
void tokenize(char *str, char tokens[][]){
int i,j; //and other such declarations
//do stuff with string and tokens, putting
//chars into the token array like so:
tokens[i][j] = <A CHAR>
}
So I realize that I can't have char tokens[][] in my tokenize function, but if I put in char **tokens instead, I get a compiler warning. Also, when I try to put a char into my char array with tokens[i][j] = <A CHAR>, I segfault.
Where am I going wrong? (And in how many ways... and how can I fix it?)
Thanks so much!
You would need to specify the size of the second dimension of the array:
#define SIZE 100
void tokenize(char *str, char tokens[][SIZE]);
This way, the compiler knows that when you say tokens[2][5] that it needs to do something like:
Find the address of tokens
Move 2 * SIZE bytes past the start
Move 5 more bytes past that address
???
Profit!
As it stands, without the second dimension specified, if you said tokens[2][5] how would it know where to go?
You're close. Arrays and pointers aren't the same thing, even though it sometimes seems like they are. You can either make your two-dimensional array out of pointers:
char **tokens = malloc(100 * sizeof(char *));
for (i = 0; i < 100; i++)
tokens[i] = malloc(100);
And then use:
void tokenize(char *str, char **tokens)
or you can specify the size of the array in your tokenize() function:
void tokenize(char *str, char tokens[][100])

Resources