SOLVED See bottom of question for solution.
I'm having trouble with passing on a String argument to my function, and am getting a segmentation fault when the function is called. The program takes in a command line input and passes on the file provided to the function after validation.
My function code goes like this:
char *inputFile; //
inputFile= argv[2];
strcpy(inputFile, argv[2]);
compress(inputFile){
//file open and creation work bug-free
//compression action to be written
void compress(char inputFile){
//compression code here
}
When the function is called, a segfault is thrown, and the value of inputFile is 0x00000000, when prior to the function call, it had a memory location and value of the test file path.
Some of the variations I've tried, with matching function prototypes:
compress(char *inputFile)
compress (char inputFile[])
I also changed the variable.
Why is a variable with a valid memory address and value in the debugger suddenly erase when used as a parameter?
Edit 1:
Incorporating suggestions here, I removed the inputFile= argv[2] line, and the debugger shows the strcpy function working.
However, I've tried both compress(char *inputFile) per Edwin Buck and compress(argv[2]) per unwind, and both changes still result in Cannot access memory at address 0xBEB9C74C
The strange thing is my file validation function checkFile(char inputFile[]) works with the inputFile value, but when I pass that same parameter to the compress(char inputFile[]) function, I get the segfault.
Edit 2- SOLVED
You know something is going on when you stump your professor for 45 min. It turns out I had declared the file read buffer as a 5MB long array inside the compress() method, which in turn maxed out the stack frame. Changing the buffer declaration to a global variable did the trick, and the code executes.
Thanks for the help!
You shouldn't be writing into memory used to hold argv[2].
You don't seem to quite understand how strings are represented; you're copying both the pointer (with the assignment) and the actual characters (with the strcpy()).
You should just do compress(argv[2]); once you've verified that that argument is valid.
First, to copy something from argv[2] to somewhere else, you need some memory for "that somewhere else". You could allocate the memory based on the size of argv[2] but for our simple example, a very large fixed size buffer will do.
char inputfile[2048];
It looks like you tried to do this by the assignment operator, which doesn't really do what you intended.
// this is not the way to what you seek, as it doesn't create any new memory for inputfile
char* inputfile = argv[2];
in passing the inputfile variable to a procedure, you want to pass much more than a single character, so void compress(char inputfile) is not an option. That leaves
compress(char *inputFile) // I prefer this one
compress (char inputFile[])
which both work, but in my experience the first is preferred, as some older compilers tend to make distinctions between pointer and array semantics. These compilers have no issues casting an array to a pointer (which is required as part of the C language specification); however, casting a pointer to an array gets a bit messy in such systems.
You've not allocated any memory for the char * to use. All you've done with char *inputfile is allocated a pointer.
Related
I'm a C beginner so my apologies if this doubt is too obvious.
What would be considered the most efficient way to solve this problem: Imagine that you have a char array ORIG and after working with it, you should have a new char array DEST. So, if I wanted to create a function for this goal, what would the best approach be:
A function that takes only one char array parameter ( argument ORIG ) and returning a char array DEST or
A void function that takes two char array arguments and does its job changing DEST as wished?
Thanks!
This very much depends on the nature of your function.
In your first case, the function has to allocate storage for the result (or return a pointer to some static object, but this wouldn't be thread-safe). This can be the right thing to do, e.g. for a function that duplicates a string, like POSIX' strdup(). This also means the caller must use free() on the result when it is no longer needed.
The second case requires the caller to provide the storage. This is often the idiomatic way to do these things in C, because in this case, the caller could just write
char result[256];
func(result, "bla bla");
and therefore use an automatic object to hold the result. It also has the benefit that you can use the actual return value to signal errors.
Both are ways of valid ways of doing it, but I'd suggest using the latter, since it means you can load the contents into any block of memory, while a returned array will have to be on heap, and be freed by design.
Again, both are valid ways of doing things, and this is just a guideline. What should be done usually depends on the situation.
It depends,
If you know that the length of DEST will be the same as the lenght of ORIG i would go for the 2nd approach because then you wont have to dynamiclly allocate memory for dest inside the function (and remember to free it outside the function).
If the length is different you have to dynamiclly allocate memory and you can do so in two ways:
1. Like your first approach - for returning array from a function in c you have to allocate a new array and return it's address(pointer)
2. The function can recieve two argument one is ORIG and second is a double pointer to RES , because the function recieves a double pointer it can allocate an array inside and return it via the argument.
1- is more "cleaner" way in terms of code ,and easier to use in terms of user expirience(the user is the caller)
Good luck!
In option 1 you will have to dynamically allocate (malloc) the output array. Which means you have a potential for a memory leak. In option 2 the output array is provided for you, so there is no chance of a leak, but there is a chance that the output array is not of sufficient size and you will get a buffer overrun when writing to it.
Both methods are acceptable, there might be a small performance difference in one compared to the other, but its really down to your choice.
Personally, being a cautios programmer, I would go for option 3:
/* Returns 0 on success, 1 on failure
Requires : inputSize <= outpuSize
input != output
input != null
output != null
*/
int DoStuff (char* output, size_t outputSize, char* input, size_t inputSize);
(Sorry if that's not proper C, its been decades:) )
(Edited in accordance with Felix Palmen's points.)
I have a problem which I figure I could solve in a matter of seconds, but I can't seem to figure it out.
What I'm trying to achieve is to create a configuration for my program and save all settings at once in my file without too much overhead.
In the past I could manually create the structure using snprintf to pass the integer into a char* which was previously allocated by memory and directly write that to file, but now instead of that, I would rather use a flat-out structure so that if I want to modify values directly, I can instead of using snprintf and atoi functions to convert strings to numbers and vice-versa.
I use the apr_file functions to open the file as I am writing an apache module.
This is my attempt that failed:
typedef struct{
unsigned int setting1;
unsigned int setting2;
} allsettings;
void read_a_file(request_rec *r){
allsettings *arecord; //compiler didn't complain at this line but might have caused segfault
apr_file_t *f;
const int perm=0x0755,ior=APR_FOPEN_READ|0,iow=APR_FOPEN_WRITE|APR_FOPEN_CREATE|0;
if (apr_file_open(&f,strres,ior,perm,r->pool)==APR_SUCCESS){
rv=apr_file_gets(arecord,sizeof(arecord),f);
rv=apr_file_close(f);
}
}
Upon compiling, I received the following error which I'm trying to work out:
warning: passing argument 1 of 'apr_file_gets' from incompatible pointer type
However, I got rid of that warning by casting argument 1 with char*.
Is there an easy way I could just load the file into two local integers to the function without having to do any string conversion or allocating extra memory into the function and without receiving a segmentation fault?
Firt of all, arp_file_gets() gets a string from a file. I believe you have to parse what you want from the string you got out. There are also somethings you need to care in the posted code segment:
1. arecord pointer is not allocated hence the pointer you passed into arp_file_gets is an invalid pointer.
2. In this call: rv=apr_file_gets(arecord,sizeof(arecord),f); I understood that you need to read out 2 unsigned int from the file f. But sizeof(arecord) = 4 (bytes) as a size of a pointer (not a struct size).
apr_file_gets "read a line from the specified file" (Apache Portable Runtime - File I/O Handling Functions.
Upon compiling, you receives the warning because the implicit cast from type struct* to type char* is not allowed (or allow just you get a warning). If you want to do that you have to cast it explicitly:
rv=apr_file_gets((char*)arecord,sizeof(arecord),f);
But, the problem with your code are the followings:
1.) The memory allocation for the record pointer missed. A possible solution is the following:
allsettings arecord;
...
rv=apr_file_gets((char*)&arecord,sizeof(arecord),f);
2.) But the main problem is that you try to use a file reader method created for character/string reading for binary reading. For example, if in your file is a "1234" string than with apr_file_gets method you will get an integer with value 0x34333231 = 875770417, not 1234. To avoid that problem you have to implement a parsing method.
Whats wrong with this C code lines
char *string()
{
char *text[20];
strcpy(text,"Hello world");
return text;
}
I was poor at pointers and I have seen this in some previous paper.
Can't able to solve.
It doesn't compile, since it treats an array of character pointers as a single array of characters.
The variable declaration line should be:
char text[200];
With that fix done, it's still broken for the reason you're probably interested in: it returns the address of a local variable (the text character array) which goes out of scope as the function returns, thus making the address invalid. There are two ways around that:
The easiest is to make the array static, since that makes it live for as long as the program runs.
You can also switch to dynamic (heap) memory by using malloc(), but that transfers ownership to the caller and requires a call to free() or memory will leak if this function gets called a lot.
Also, as a minor point, its name is in a reserved name space (user programs cannot define functions whose names begin with str). Also, a function taking no arguments should be declared as (void) in C, an empty pair of parentheses does not mean the same thing.
This code will not compile because you are trying to make an array of pointers.
In simple words if you want to handle string using pointer you can do using following:
char *str="HELLO WORLD";
And if you want to handle string using char array you have to remove value at address operator(*).
here it is:
char text[20];
then you can perform your function.
Still there is error as the Scope of the text is only valid inside the function so if you want to pass address and retain the value make it static
static char text[20];
return text;
I'm working on a compression algorithm wherein we have to write code in C. The program takes a file and removes the most significant bit in every character and stores the compressed text in another file. I wrote a function called compress as shown below. I'm getting a seg fault while freeing out_buf. Any help will be a great pleasure.
You close out_fd twice, so of course the second time it is an invalid file descriptor. But more than that, you need to review your use of sizeof() which is NOT the same as finding the buffer size of a dynamically-allocated buffer (sizeof returns the size of the pointer, not the buffer). You don't show the calling code, but using strcat() on a buffer passed-in is always worth a look too (is the buffer passed by the caller large enough for the result?).
Anyway, that should be enough to get you going again...
You're closing twice the same file descriptor
close(out_fd);
if ( close(out_fd) == -1 )
oops("Error closing output file", "");
Just remove the first close(out_fd)
The segmentation fault is because you moved the out_buf pointer.
If you want to put values inside his malloc'd area, use another temp pointer and move it through this memory area.
Like this:
unsigned char *out_buf = malloc(5400000*7/8);
unsigned char *tmp_buf = out_buf;
then subst every *out_buf++ with *tmp_buf++;
Change also the out_buf inside the write call with tmp_buf
I'm trying to write a simple C program on Ubuntu using Eclipse CDT (yes, I'm more comfortable with an IDE and I'm used to Eclipse from Java development), and I'm stuck with something weird. On one part of my code, I initialize a char array in a function, and it is by default pointing to the same location with one of the inputs, which has nothing to do with that char array. Here is my code:
char* subdir(const char input[], const char dir[]){
[*] int totallen = strlen(input) + strlen(dir) + 2;
char retval[totallen];
strcpy(retval, input);
strcat(retval, dir);
...}
Ok at the part I've marked with [*], there is a checkpoint. Even at that breakpoint, when I check y locals, I see that retval is pointing to the same address with my argument input. It not even possible as input comes from another function and retval is created in this function. Is is me being unexperienced with C and missing something, or is there a bug somewhere with the C compiler?
It seems so obvious to me that they should't point to the same (and a valid, of course, they aren't NULL) location. When the code goes on, it literally messes up everything; I get random characters and shapes in console and the program crashes.
I don't think it makes sense to check the address of retval BEFORE it appears, it being a VLA and all (by definition the compiler and the debugger don't know much about it, it's generated at runtime on the stack).
Try checking its address after its point of definition.
EDIT
I just read the "I get random characters and shapes in console". It's obvious now that you are returning the VLA and expecting things to work.
A VLA is only valid inside the block where it was defined. Using it outside is undefined behavior and thus very dangerous. Even if the size were constant, it still wouldn't be valid to return it from the function. In this case you most definitely want to malloc the memory.
What cnicutar said.
I hate people who do this, so I hate me ... but ... Arrays of non-const size are a C99 extension and not supported by C++. Of course GCC has extensions to make it happen.
Under the covers you are essentially doing an _alloca, so your odds of blowing out the stack are proportional to who has access to abuse the function.
Finally, I hope it doesn't actually get returned, because that would be returning a pointer to a stack allocated array, which would be your real problem since that array is gone as of the point of return.
In C++ you would typically use a string class.
In C you would either pass a pointer and length in as parameters, or a pointer to a pointer (or return a pointer) and specify the calls should call free() on it when done. These solutions all suck because they are error prone to leaks or truncation or overflow. :/
Well, your fundamental problem is that you are returning a pointer to the stack allocated VLA. You can't do that. Pointers to local variables are only valid inside the scope of the function that declares them. Your code results in Undefined Behaviour.
At least I am assuming that somewhere in the ..... in the real code is the line return retval.
You'll need to use heap allocation, or pass a suitably sized buffer to the function.
As well as that, you only need +1 rather than +2 in the length calculation - there is only one null-terminator.
Try changing retval to a character pointer and allocating your buffer using malloc().
Pass the two string arguments as, char * or const char *
Rather than returning char *, you should just pass another parameter with a string pointer that you already malloc'd space for.
Return bool or int describing what happened in the function, and use the parameter you passed to store the result.
Lastly don't forget to free the memory since you're having to malloc space for the string on the heap...
//retstr is not a const like the other two
bool subdir(const char *input, const char *dir,char *retstr){
strcpy(retstr, input);
strcat(retstr, dir);
return 1;
}
int main()
{
char h[]="Hello ";
char w[]="World!";
char *greet=(char*)malloc(strlen(h)+strlen(w)+1); //Size of the result plus room for the terminator!
subdir(h,w,greet);
printf("%s",greet);
return 1;
}
This will print: "Hello World!" added together by your function.
Also when you're creating a string on the fly you must malloc. The compiler doesn't know how long the two other strings are going to be, thus using char greet[totallen]; shouldn't work.