I have some problems with a pointer. My idea was to pass a buffer to a function in order to store the return data in this buffer. But, I do not know if it will work.
void main()
{
char *buf = malloc(sizeof(char) *buf);
memset(buf, 0x00, BUF_SIZE);
sendCommand(buf);
}
sendCommand(char *buf)
{
write(fd, "some commands", strlen("some commands"));
readResponse(buf);
}
readResponse(char *buf)
{
read(fd, buf, nbytes);
}
I know there is no error handling up to now. And some variables are not well defined. It just depends on the passing buffer. Will I see the data that I get in readResponse() in my main function?
As in readResponse() as you read nbytes into buffer pointed by buf ,so you will get that data in main .
Some improvements to be done -
1. void main() -> int main(void) or int main(int argc, char *argv[])
2. char *buf = malloc(sizeof(char) *buf); -> char *buf = malloc(BUF_SIZE); // sizeof(char)=1 or maybe something you desire (not sure though what you want ??)
Note - remember to free allocated memory.
You have a remarkable number of significant problems in the code you presented, considering how short it is. Other answers have addressed those, though, and your question is not actually about any of them:
Will I see the data I get in readResponse() in my main function?
Yes, provided that argument buf is a pointer to an array large enough to accommodate nbytes bytes, and that the read() call in fact successfully reads any bytes, those bytes will afterward be visible in main() via the pointer it passed to readResponse(). More generally, if you pass a pointer as a function argument, the called function may manipulate the pointed-to object, including by modifying those parts of it that are not const. That's how the read() function itself is able to store the bytes it reads into your buffer, after all.
This won't do what you think it does:
char *buf = malloc(sizeof(char) *buf);
Did you mean to multiply with BUF_SIZE?
Related
I need to be able to check in a kernel module whether or not a file descriptor, dentry, or inode falls under a certain path. To do this, I am going to have to write a function that when given a dentry or a file descriptor (not sure which, yet), will return said object's full path name.
What is the way to write a function that returns variable-length strings?
You can try like this:
char *myFunction(void)
{
char *word;
word = malloc (sizeof (some_random_length));
//add some random characters
return word;
}
You can also refer related thread: best practice for returning a variable length string in c
The typical way to do this in C, is not to return anything at all:
void func (char* buf, size_t buf_size, size_t* length);
Where buf is a pointer to the buffer which will hold the string, allocated by the caller. buf_size is the size of that buffer. And length is how much of that buffer that the function used.
You could return a pointer to buf as done by for example strcpy. But this doesn't make much sense, since the same pointer already exists in one of the parameters. It adds nothing but confusion.
(Don't use strcpy, strcat etc functions as some role model for how to write functions. Many C standard library functions have obscure prototypes, because they are so terribly old, from a time when good programming practice wasn't invented, or at least not known by Dennis Ritchie.)
There are two common approaches:
One is to have a fixed size buffer to store the result:
int makeFullPath(char *buffer,size_t max_size,...)
{
int actual_size = snprintf(buffer,max_size,...);
return actual_size;
}
Examples of standard functions which use this approach are strncpy() and snprintf(). This approach has the advantage that no dynamic memory allocation is needed, which will give better performance for time-critical functions. The downside is that it puts more responsibility on the caller to be able to determine the largest possible result size in advance or be ready to reallocate if a larger size is necessary.
The second common approach is to calculate how big of a buffer to use and allocate that many bytes internally:
// Caller eventually needs to free() the result.
char* makeFullPath(...)
{
size_t max_size = calculateFullPathSize(...);
char *buffer = malloc(max_size);
if (!buffer) return NULL;
int actual_size = snprintf(buffer,max_size,...);
assert(actual_size<max_size);
return buffer;
}
An example of a standard function that uses this approach is strdup(). The advantage is that the caller no longer needs to worry about the size, but they now need to make sure that they free the result. For a kernel module, you would use kmalloc() and kfree() instead of malloc() and free().
A less common approach is to have a static buffer:
const char *makeFullPath(char *buffer,size_t max_size,...)
{
static char buffer[MAX_PATH];
int actual_size = snprintf(buffer,MAX_PATH,...);
return buffer;
}
This avoids the caller having to worry about the size or freeing the result, and it is also efficient, but it has the downside that the caller now has to make sure that they don't call the function a second time while the result of the first call is still being used.
char *result1 = makeFullPath(...);
char *result2 = makeFullPath(...);
printf("%s",result1);
printf("%s",result2); /* oops! */
Here, the caller probably meant to print two separate strings, but they'll actually just get the second string twice. This is also problematic in multi-threaded code, and probably unusable for kernel code.
For example:
char * fn( int file_id )
{
static char res[MAX_PATH];
// fill res[]
return res;
}
/*
let do it the BSTR way (BasicString of VB)
*/
char * CopyString(char *str){
unsigned short len;
char *buff;
len=lstrlen(str);
buff=malloc(sizeof(short)+len+1);
if(buff){
((short*)buff)[0]=len+1;
buff=&((short*)buff)[1];
strcpy(buff,str);
}
return buff;
}
#define len_of_string(s) ((short*)s)[-1])
#define free_string(s) free(&((short*)s)[-1]))
int main(){
char *buff=CopyString("full_path_name");
if(buff){
printf("len of string= %d\n",len_of_string(buff));
free_string(buff);
}else{
printf("Error: malloc failed\n");
}
return 0;
}
/*
now you can imagine how to reallocate the string to a new size
*/
I'm trying to read into a buffer passed as a pointer to this function. memcpy() works fine and the data is stored correctly in buffer, but when I access buffer outside of the function it is null. There's some pointer issue I'm not getting here.
Here's the code, I took out most of it, I know it copies the data correctly, but it doesn't pass it to the buffer pointer. Ideas?
int read(file file, char *buffer , int maxlen) {
int bytes_read;
// copy data to file buffer
bytes_read = min(maxlen, file->file_size - file->cursor);
buffer = (char*) malloc(bytes_read);
memcpy(buffer , file->buffer + file->cursor, bytes_read);
return bytes_read;
}
The problem is pretty simple: you are modifying the variable "buffer". Since it is passed by value and not by reference, the calling function doesn't see the change. In order to make the change to buffer visible, you need to pass in a pointer to buffer.
Your function would then look like this:
int read(file file, char **buffer , int maxlen) {
int bytes_read;
// copy data to file buffer
bytes_read = min(maxlen, file->file_size - file->cursor);
*buffer = (char*) malloc(bytes_read);
memcpy(*buffer , file->buffer + file->cursor, bytes_read);
return bytes_read;
}
to call the function:
rv = read(file, &buffer, maxlen);
You cannot modify buffer directly because C uses pass by value with parameters. Therefore it is a copy of the pointer you are modifying. To change the pointer you need to change your function prototype to take a char** and allocate to the first level of indirection on that.
As a crude example of this:
void read(char** buffer , int byte_size) {
*buffer = (char*) malloc(byte_size);
}
and use where required with something like
char* buffer;
read(&buffer,10); /* now buffer points to dynamically allocated array of 10 chars */
If I have a pointer to a message buffer how do I memcpy() into that buffer? For example say I have the following:
char **buffer;
char data[10]
memcpy(*buffer, data, 10);
But this doesn't seem to work and always crashes my program, however the compiler doesn't see to mind. Can someone please tell me why? Btw the reason I have a char **buffer is because its being passed as a parameter of the function.
The pointer variable buffer does not point to anything. You need to allocate memory and make buffer point to it. For instance:
buffer = malloc(sizeof(*buffer));
*buffer = malloc(10);
memcpy(*buffer, data, 10);
I have a function of which I need to return the time for another logging function, and it looks like this:
//put time in to buf, format 00:00:00\0
void gettimestr(char buf[9]) {
if(strlen(buf) != 9) { //experimental error checking
fprintf(stderr, "Buf appears to be %d bytes and not 9!\n", strlen( buf ));
}
time_t cur_time;
time(&cur_time);
struct tm *ts = localtime(&cur_time);
sprintf(buf, "%02d:%02d:%02d",
ts->tm_hour,
ts->tm_min,
ts->tm_sec );
strncat(buf, "\0", 1);
}
Now I guess the main problem is checking if the buffer is long enough, sizeof() returns a pointer size and strlen seems to randomly return 0 or something such as 12 on two different calls.
My first question is, how would I be able to detect the size of the buffer safely, is it possible?
My other question is, is accepting buf[9] a favourable method or should I accept a pointer to a buffer, and use strcat() instead of sprintf() to append the time to it? sprintf makes it easier for padding zeros to the time values, although it seems to only accept a character array and not a pointer.
Your function assumes that the buffer being passed in already contains a null-terminated string with 9 characters. That doesn't make sense.
The proper way would be to request the size as an argument:
void gettimestr(char *buf, int bufferSize) {
and use snprintf:
snprintf(buf, bufferSize, "%02dx....", ....);<sub>*</sub>
And terminate the string since snprintf won't do that if you exceed the limit:
buf[bufferSize-1] = 0;
You can call your function like this:
char buffer[16];
gettimestr(buffer, sizeof(buffer));
There is no other way to determine the size. This isn't Java where an array knows its size. Passing a char * will simply send a pointer down to the function with no further information, so your only way to get the size of the buffer is by requiring the caller to specify it.
(EDIT: snprintf should always terminate the string properly, as pointed out in the comments.)
#EboMike is right. Just to complement his answer, you could check the buffer with:
void gettimestr(char *buf, int bufferSize) {
if (!buf) {
fprintf(stderr, "Null buffer\n");
return;
}
// rest of the code
}
I have set the buffer to size 100.
I display the buffer in the main function where the buffer is declared.
However, when I pass the buffer to the function and get the sizeof '4',
I was thinking it should be 100, as that is the size of the buffer that I
created in main.
output:
buffer size: 100
sizeof(buffer): 4
#include <string.h>
#include <stdio.h>
void load_buffer(char *buffer);
int main()
{
char buffer[100];
printf("buffer size: %d\n", sizeof(buffer));
load_buffer(buffer);
return 0;
}
void load_buffer(char *buffer)
{
printf("sizeof(buffer): %d\n", sizeof(buffer));
}
You are using the size of the pointer to the buffer (4 bytes), rather than the size of the buffer.
In C, you have to pass the size of the buffer separately, which is part of the reason buffer overruns happen so easily and frequently.
void load_buffer(char * buffer, size_t bufSize)
{
...
}
The answers by Mitch Wheat and hhafez are completely right and to the point. I'm going to show some additional information which may prove useful sometimes.
Note that the same happens if you tell the compiler that you have an array of the right size
void load_buffer(char buffer[100]) {
/* prints 4 too! */
printf("sizeof(buffer): %d\n", sizeof(buffer));
}
An array as parameter is just declaring a pointer. The compiler automatically changes that to char *name even if it was declared as char name[N].
If you want to force callers to pass an array of size 100 only, you can accept the address of the array (and the type of that) instead:
void load_buffer(char (*buffer)[100]) {
/* prints 100 */
printf("sizeof(buffer): %d\n", sizeof(*buffer));
}
It's a pointer to the array you have in main, so you need to dereference in the function to get the array. Indexing then is done by
buffer[0][N] or (*buffer)[N]
Nobody I know is doing that and I'm neither doing it myself, because it rather complicates passing of the argument. But it's good to know about it. You can call the function like this then
load_buffer(&buffer)
If you want to accept other sizes too, i would go with the passing-N option the other two answers recommend.
From the OP
void load_buffer(char *buffer)
{
printf("sizeof(buffer): %d\n", sizeof(buffer));
}
Even though you can imagine that load_buffer() is passed the buffer by refrence, what is really happening is you are passing a pointer to char by value. The actual array is not passed so there is no way for the load_buffer() function to know the size of the buffer array
So what is sizeof(buffer) doing? It is simply returning the size of a pointer to char. If load_buffer() needs the size of the buffer it needs to be passed speratly.
Or you can create a new struct that contains both a char array and the size of the array, and pass a pointer to that struct instead, that way the buffer and it's size are always together ;)
What happens, is when you pass an array to a function, you only pass the address of the array in the memory, not the size of the array. What sizeof(buffer) is outputting in load_buffer() is the size of the pointer, which is four bytes.
The best way to keep the size of the buffer in the function is to change the function to:
void load_buffer(char *buffer, int length);
and the call to:
load_buffer(buffer, sizeof(buffer));
and then use length whenever you want the size of buffer.