void GetMemory(char *p)
{
p = (char *)malloc(100);
}
void Test(void)
{
char *str = NULL;
GetMemory(str);
strcpy(str, "hello world");
printf(str);
}
PHP中文网2017-04-17 11:12:58
The questioner seems not to know much about C language. It is recommended to read basic tutorials such as "K & R".
You are trying to point GetMemory()
to a memory allocated by *str
via malloc()
.
However, function parameters in C language are passed by value. The value *str
of NULL
is copied to *p
, and then *p
is pointed to the value returned by malloc()
. At this time, GetMomory()
The function ends. The value of *str
remains NULL
, nothing has changed. After that, you use strcpy
to try to copy "hello world"
to NULL
, but of course something goes wrong.
The correct approach is to pass the address of the pointer variable *str
to GetMemory(char **p)
. *str
itself is a pointer, pointing to an address. Although *str
is a pointer, a pointer also has its own address. Pass the address of *str
to **p
, and **p
will be a pointer to the pointer.
At this point, your main problem has been solved. You can skip the rest and look directly at the code .
free()
After the program exits, the operating system will automatically release all memory. However, it is never wrong to release memory immediately after using it.
printf()
Usage errorAlso, your usage of printf()
is wrong. The parameters of printf()
cannot directly be the data to be printed. A literal string with a conversion specifier is required, and the following parameters are the actual parameters to be formatted.
Some people say that according to the prototype of printf()
, there is no problem in directly following a string printf(str)
. However, str
can lead to serious security issues if the content is obtained externally, such as user input. Both GCC and Clang will issue warnings about such usage.
For example, on old 32-bit Linux:
#include <stdio.h>
int main(int argc, char **argv)
{
char *secret = "This is a secret!\n";
printf(argv[1]);
return 0;
}
If compiled using -mpreferred-stack-boundary=2
$ gcc -mpreferred-stack-boundary=2 FormatString.c -o FormatString
$ ./FormatString %s
This is a secret!
Oh? why is that? I don’t know much about the bottom layer, I can only say that this is related to the memory out of bounds of varargs
, and *secret
happens to be at this memory address. Have you ever thought of the "Heartbleed" vulnerability that was exposed in OpenSSL some time ago?
-mpreferred-stack-boundary=2
is not a necessary means of attack. Given the right conditions and careful calculation, the harm could be much greater than this.
Therefore such usage must be prohibited and
should be usedprintf("%s\n", str);
or
puts(str);
#include
any header filesBefore using the library function, you need to #include
provide the header file of the corresponding function.
printf()
Powered by stdio.h
malloc()
Powered by stdlib.h
strcpy()
Powered by string.h
main()
functionmain()
The function is the entrance of the program. Without the entrance, where would the program be executed?
The corrected procedure is as follows.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void GetMemory(char **p)
{
*p = (char *)malloc(100);
}
void Test(void)
{
char *str = NULL;
GetMemory(&str);
strcpy(str, "hello world");
printf("%s\n", str);
free(str);
*str = NULL; // 避免误用已悬空的指针
}
int main(void)
{
Test();
return 0;
}
天蓬老师2017-04-17 11:12:58
Damn it... you don't support posting codes in the answer comments, so I'll add another answer. Some comments on the best answer
int printf ( const char * format, ... );
Therefore, printf(str)
is feasible.
However, if str
is content entered by the user or obtained externally, str
may contain malicious code, which can be used to carry out memory overflow and execute arbitrary code attacks. Therefore, doing so should be strictly prohibited. ——Biergaizi
char* GetMemory()
{
char* p = (char *)malloc(100);
memset(p, 0, SIZE); // or *p = 0;
return p;
}
The following code is compiled on win7 and runs successfully
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 100
void GetMemory(char **p)
{
*p = (char *)malloc(
memset(*p, 0, SIZE); // or **p = 0;
}
void Test(void)
{
char *str = NULL;
GetMemory(&str);
strcpy(str, "hello world");
printf(str);
free( str);
str = NULL;
}
int main(void)
{
Test();
return 0;
}
黄舟2017-04-17 11:12:58
The simplest answer is that the poster didn’t understand: Pass by reference and pass by value
If you want to modify the content pointed to by str, you have to pass the pointer to str