here i have one function which is call many times in one application this application is running continuously.
Here i am take one character array size of 1024.
here i am declaring char input[1024];
so which is best way
1) char input[1024];
2) char input[1024] = NULL;
this thing will not create any memory issue after so many times if we used this function.char input[1024];
i think may be after using input we have to make NULL ?
or in declaration we have to declare this thing as char input[1024] = NULL; so when it will be called next time so that time first input make null than its taking any memory.
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
void do() {
char input[1024];
strcat(input,"ussp-push 04:18:0F:B1:48:B5#9");
strcat(input,"> dev/null&");
if(system(input) != 0)
{
printf("\nFailed command\n");
}
else
{
printf("\nSuccesss command\n");
}
}
Your program does not initialise input at all. This can lead to buffer overrun and even if that does not happen, your program is likely to have incorrect results. Thus your code invokes undefined behaviour.
Presumably you actually want to initialize input to be an empty string. Like this:
char input[1024] = "";
Once you have done this your calls to strcat will work.
If you don't want to initialise input then you can use strcpy instead of the first strcat:
char input[1024];
strcpy(input, "ussp-push 04:18:0F:B1:48:B5#9");
If ever you need to assign the empty string to input later in the code do it like this:
input[0] = '\0';
The code you suggest, char input[1024] = NULL is not valid. It does not compile.
As you're not changing it inside the function, make it a static const array
void dostuff() {
static const char input[] = "ussp-push 04:18:0F:B1:48:B5#9> dev/null&";
if (system(input) != 0)
{
printf("\nFailed command\n");
}
else
{
printf("\nSuccesss command\n");
}
}
strcat appends a string to another, and to do so it searches in the destination string the terminator char (\0). Since you didn't initialize the destination string, it may or may not find the \0 in that.
just initialize it, for example with:
input[0]='\0';
This will not compile:
char input[1024] = NULL;
$ make nullarray
cc nullarray.c -o nullarray
nullarray.c: In function ‘main’:
nullarray.c:4:2: error: invalid initializer
make: *** [nullarray] Error 1
$
When you declare char input[size], the compiler will cause the function prototype to allocate that much memory on the stack (if in a function) or in the .bss or .data section (if at top-level), and you cannot assign NULL to the array to try to stop it.
Perhaps a take step back and describe what problem you're really trying to solve? Should you be using malloc(3) to allocate memory instead?
This will not cause memory issues. Each time do() is called, an array of 1024 bytes will be allocated on the stack; that memory will be used for input throughout that call of do(). When do() returns, the 1024 bytes will be freed, and a (conceptually) new set of 1024 will be allocated on the next invocation.
In any case char input[1024] = NULL; is not valid code. If you want to initialise input, try something like char input[1024] = ""; instead.
Related
I am trying to fill the gaps in my self-education in computer science and taking the CS50 course on Edx. I am completely new to C. In one of the problems sets, I have to compare strings encrypted with crypt function.
In the following example, I cannot understand why strcmp returns 0 (i.e. 'claims' that the strings are equal:
#include <crypt.h>
#include <stdio.h>
#include <string.h>
#define _XOPEN_SOURCE
int main(void)
{
char string1[4] = "foo\0";
char string2[4] = "bar\0";
printf("crypt1: %s\n",crypt(string1, "50\0"));
printf("crypt2: %s\n",crypt(string2, "50\0"));
if (strcmp(crypt(string1, "50\0"),crypt(string2, "50\0")) == 0)
{
printf("crypt1: %s\n",crypt(string1, "50\0"));
printf("crypt2: %s\n",crypt(string2, "50\0"));
return 0;
}
}
When I run the program, the output value is:
crypt1: 50GbL/FUeE/J6
crypt2: 50hmnpE.bRNiU
crypt1: 50GbL/FUeE/J6
crypt2: 50hmnpE.bRNiU
How is it possible, that the code inside if condition is even executed?
Apparently, crypt() uses the same buffer for the encrypted string on each call:
char string1[] = "foo";
char string2[] = "bar";
char *crypt1 = crypt(string1, "50");
printf("crypt1: %s\n", crypt1); // crypt1: 50GbL/FUeE/J6
char *crypt2 = crypt(string2, "50");
printf("crypt1: %s\n", crypt1); // crypt1: 50hmnpE.bRNiU
printf("crypt2: %s\n", crypt2); // crypt2: 50hmnpE.bRNiU
In order to keep (and compare) both results, you have to strdup()
them or copy them to a separate array.
As mentioned in Martin's comment, crypt returns a pointer to a static buffer that is overwritten on each call. So strcmp is actually being passed the same buffer - the first value of crypt already having been overwritten by the second - once the two arguments have been evaluated.
Related to the following: C crypt function, malloc and valgrind
[And, for what its worth, in C, any function that returns a string (char *) has to get the memory for that string from somewhere. You either need to pass the buffer in as an argument, or it needs to find it itself. And because C doesn't do garbage collection and requires manual memory management (e.g. malloc/free), a function that does not take a result buffer as an argument should throw up a red flag - is the result a static buffer (that gets overwritten like this)? does it need to be free'd when I'm done with it? Otherwise, you risk memory leaks or bugs like the one you're experiencing.)
Having some issues comparing char arrays thru pointers. I am working without both the string library and iostream, would like to keep it that way.
char *GetCurrentPath()
{
char buffer[MAX_PATH];
if (!GetModuleFileNameA(NULL, buffer, MAX_PATH)) {
printf("GetModuleFileNameA failed, error: %d\n", GetLastError());
}
return (buffer);
}
char *GetInstallPath()
{
char buffer[MAX_PATH];
if (!SHGetSpecialFolderPathA(NULL, buffer, CSIDL_APPDATA, FALSE)) {
printf("SHGetSpecialFolderPathA failed, error: %d\n", GetLastError());
}
strcat(buffer, "\\service.exe");
return (buffer);
}
char *InstallPath = GetInstallPath();
char *CurrentPath = GetCurrentPath();
if (InstallPath == CurrentPath)......
The if statement causes an instant crash, same goes for strcomp.
Suggestions?
What you are currently doing is undefined behavior. The buffers that you are using in the two functions are defined locally to those functions and go out of scope the moment the functions end, giving you pointers to random stack addresses.
You need to either allocate the buffers in the functions:
Replace : char buffer[MAX_PATH];
With: char *buffer = new char[MAX_PATH]
Or pass allocated buffers from your main to the functions:
char *InstallPath = new char[MAX_PATH];
GetInstallPath(InstallPath);
And change your get path functions:
char *GetInstallPath(char *buffer)
In both cases, you will have to delete your pointers before ending your program to free up the memory.
On top of that, when you try to compare the two variables, they will compare pointer addresses rather than string contents. You will need to use strcmp() or something in that family of functions.
Your functions return an array (char *) declared locally inside them. Your pointers have undefined values outside the functions. You can't do that.
You may allocate them dynamically:
char *buffer = malloc(MAX_PATH*sizeof(char));
Since both buffers are allocated on stack, they are freed after the function execution ends. So, the pointers function returns becomes invalid.
To fix that, you have to allocate buffer[] on heap, using char * buffer = new char[MAX_PATH];
But after you will have to free the memory manually.
After going through multiple examples of passing a string by value in C, I still don't understand why the following code does not work
int main(void){
char *fileList;
strcpy(fileList,"This is a test line\n");
char type = 'F';
if(checkFileList(fileList, type)){
printf("Proper File list\n");
}
else{
printf("Improper File list\n");
}
}
int checkFileList(char *string, char type){
// Do something with string
}
This program works if I define the variable fileList in the main function as-
char fileList[128];
But I can't provide a fixed size to this string as I get the string only at runtime and hence don't know how long it'll be.
What am I doing wrong here? Please note that I don't want to pass the string by reference as I'll be changing the string in the function and don't want this to be reflected in the original string.
In your code
char *fileList;
strcpy(fileList,"This is a test line\n");
invokes undefined behaviour
, as , fileList is used uninitialized.
You need to allocate memory to fileList before using it. Maybe malloc() and family of functions will help you into that. Also, read about free().
FWIW,
This program works if I define the variable fileList in the main function as-
char fileList[128];
because, the fileList is an array here and the memory allocation is already done by the compiler. So, it is ok to use that.
BTW "Passing string by value" is misuse of the terms. C uses pass-by-value for any function parameter passing.
In order to allocate the memory for the string at runtime you better get to know the size of the string first:
int main(void){
const char *str = "This is a test line\n";
int len = strlen(str);
char *fileList = malloc(len);
// then later you also have to take care for releasing the allocated memory:
free(fileList);
}
The following C program attempts to fetch and print the host name of the current RHEL host. It throws a segmentation fault on this machine. As per the definition of gethostname I should be able to pass a char pointer, shouldn't I?
When I use a char array instead (like char hname[255]), the call to gethostname works. (If I did this how would I return the array to main?)
#include <stdio.h>
#include <unistd.h>
char * fetchHostname()
{
// using "char hname[255]" gets me around the issue;
// however, I dont understand why I'm unable to use
// a char pointer.
char *hname;
gethostname(hname, 255 );
return hname;
}
int main()
{
char *hostname = fetchHostname();
return 0;
}
Output:
pmn#rhel /tmp/temp > gcc -g test.c -o test
pmn#rhel /tmp/temp >
pmn#rhel /tmp/temp > ./test
Segmentation fault
pmn#rhel /tmp/temp >
As gethostname man said:
The gethostname() function shall return the standard host name for
the current machine. The namelen argument shall
specify the size of the array pointed to by the name argument.
The returned name shall be null-terminated, except that
if namelen is an insufficient length to hold the host name,
then the returned name shall be truncated and it is
unspecified whether the returned name is null-terminated.
You need a place to store the function information, so declare hostname as an array, not a pointer.
#include <unistd.h>
char * fetchHostname(char *hostname, int size)
{
// using "char hname[255]" gets me around the issue;
// however, I dont understand why I'm unable to use
// a char pointer.
gethostname(hostname, size);
return hostname;
}
int main()
{
char hostname[HOST_NAME_MAX + 1];
fetchHostname(hostname, HOST_NAME_MAX);
return 0;
}
When I use a char array instead (like char hname[255]), the call to
gethostname works. (If I did this how would I return the array to
main?)
By passing a pointer to the array from main() to your function. Note that this approach makes your function fetchHostname() to be just a wrapper for function gethostname():
#include <stdio.h>
#include <unistd.h>
void fetchHostname(char *hname)
{
gethostname(hname,255);
}
int main()
{
char hostname[256];
fetchHostname(hostname);
return 0;
}
Or by declaring your hname[] array local static, so it is valid even after the program leaves the function (this approach is not thread-safe):
#include <stdio.h>
#include <unistd.h>
char *fetchHostname (void)
{
static char hname[256];
gethostname(hname,255);
return hname;
}
int main()
{
char *hostname;
hostname = fetchHostname();
return 0;
}
Though there are many technically correct answers I don't think that they actually explain to you where you went wrong.
gethostname(char *name, size_t len); is documented here and it basically says that the parameter name is an array of characters that you have allocated where this function will copy the hostname into. And how you do that is explained in the many other wonderful answers here.
That is why this works if you make the array yourself but causes a segmentation fault if you just give it a pointer.
Also, you were giving this function an uninitialized pointer so when it tried to copy data to that address (which is just some completely random place in memory) it caused your program to terminate because it was trying to write a string where it isn't allowed to.
This type of mistake tells me that you need to brush up on what pointers actually are and that you need to understand that they can be used to allow a function to return a value in a different way than using the return statement.
Update: please see #Tio Pepe's answer.
You need to allocate space in your array (either statically or dynamically):
char hname[HOST_NAME_MAX + 1];
otherwise you are passing an uninitialised pointer that could point anywhere.
Your call to gethostname():
gethostname(hname, 255);
is a contract that says here is a pointer that points to at least 255 characters of allocated space.
Also, you are trying to return a pointer to space allocated on the stack. That's not good.
Yoi need to dynamically allocate the character array if you want to return it.
char * hname;
hname = malloc((HOST_NAME_MAX +1) * sizeof(char));
But be aware that you now have to manage when that space gets freed.
Returning a pointer to a local variable is undefined behavior, because it will go out of scope. If you allocate it on the heap (via dynamic allocation), you will not have this problem.
char * fetchHostname()
{
char* hname= malloc(sizeof(char) * 256);
gethostname(hname, 255);
return hname;
}
int main()
{
char *hostname = fetchHostname();
printf(hostname);
free(hostname);
return 0;
}
char *hname; //defined inside a function and would be destroyed after the function is executed
After the execution of fetchHostname() the address returned to the hostname is not valid and acessing it would result in segmentation fault
I'm trying to get input from the user while allocating it dynamically and then "split" it using strtok.
Main Questions:
Im getting an infinite loop of "a{\300_\377" and ",".
Why do i get a warning of "Implicitly declaring library function "malloc"/"realoc" with type void"
Other less important questions:
3.i want to break, if the input includes "-1", how do i check it? As you can see it breaks now if its 1.
4.In the getsWordsArray() i want to return a pointer to an array of strings. Since i dont know how many strings there are do i also need to dynamically allocate it like in the getInput(). (I dont know how many chars are there in each string)
int main(int argc, const char * argv[])
{
char input = getInput();
getWordsArray(&input);
}
char getInput()
{
char *data,*temp;
data=malloc(sizeof(char));
char c; /* c is the current character */
int i; /* i is the counter */
printf ("\n Enter chars and to finish push new line:\n");
for (i=0;;i++) {
c=getchar(); /* put input character into c */
if (c== '1') // need to find a way to change it to -1
break;
data[i]=c; /* put the character into the data array */
temp=realloc(data,(i+1)*sizeof(char)); /* give the pointer some memory */
if ( temp != NULL ) {
data=temp;
} else {
free(data);
printf("Error allocating memory!\n");
return 0 ;
}
}
printf("list is: %s\n",data); // for checking
return *data;
}
void getWordsArray(char *input)
{
char *token;
char *search = " ,";
token = strtok (input,search);
while (token != NULL ) {
printf("%s\n",token);
token = strtok(NULL,search);
}
}
EDIT:
i noticed i forgot to "strtok" command so i changed it to token = strtok(NULL,search);
I still get wierd output on the printf:
\327{\300_\377
Change:
int main(int argc, const char * argv[])
{
char input = getInput();
getWordsArray(&input);
}
to:
int main(int argc, const char * argv[])
{
char *input = getInput();
getWordsArray(input);
}
with a similar to the return value of getInput():
char *getInput()
{
// ...
return data;
}
In your code, you were only saving the first character of the input string, and then passing mostly garbage to getWordsArray().
For your malloc() question, man malloc starts with:
SYNOPSIS
#include <stdlib.h>
For your getchar() question, perhaps see I'm trying to understand getchar() != EOF, etc.
Joseph answered Q1.
Q2: malloc and realoc returns type void *. You need to explicitly convert that to char *. Try this:
data = (char *) malloc(sizeof(char));
Q3: 1 can be interpreted as one character. -1, while converting to characters, is equivalent to string "-1" which has character '-' and '1'. In order to check against -1, you need to use strcmp or strncmp to compare against the string "-1".
Q4: If you are going to return a different copy, yes, dynamically allocate memory is a good idea. Alternatively, you can put all pointers to each token into a data structure like a linked list for future reference. This way, you avoid making copies and just allow access to each token in the string.
Things that are wrong:
Strings in C are null-terminated. The %s argument to printf means "just keep printing characters until you hit a '\0'". Since you don't null-terminate data before printing it, printf is running off the end of data and just printing your heap (which happens to not contain any null bytes to stop it).
What headers did you #include? Missing <stdlib.h> is the most obvious reason for an implicit declaration of malloc.
getInput returns the first char of data by value. This is not what you want. (getWordsArray will never work. Also see 1.)
Suggestions:
Here's one idea for breaking on -1: if ((c == '1') && (data[i-1] == '-'))
To get an array of the strings you would indeed need a dynamic array of char *. You could either malloc a new string to copy each token that strtok returns, or just save each token directly as a pointer into input.