c char指针内存和全局变量

时间:2015-06-26 17:41:12

标签: c pointers

在释放我用来设置c中的值的本地资源后,指向我的全局变量的指针变为crud。

这是.c类

char* resource_directory;
void getResourcePath()
{
  char *basePath = SDL_GetBasePath();
  char* resource_dir = (char*)malloc(37 * sizeof(char));

  for(int i = 0; i < 25; i++)
  {
    resource_dir[i] = basePath[i];
  }
  strcat(resource_dir, "resources/");
  resource_dir[36] = '\0';

  *resource_directory = *resource_dir;
  free(basePath);
  // free(resource_dir); <--- If I free here the value goes to crud
}

(下面的这一行应该说resresource_directorydir的值等于resource_dir的值)对吗?

*resource_directory = *resource_dir;

所以第一个指针的地址处的值应该是第二个地址的值,但是在尝试将资源释放到函数末尾之后。

即使对地址进行打印声明也表明它们有不同的地址。

SDL_Log("%d, %d", &resource_directory, &resource_dir);

示例输出: 245387384, 1361037488

我觉得我在这里犯了一个愚蠢的错误,但我不知道它是什么。

3 个答案:

答案 0 :(得分:1)

这一行,

*resource_directory = *resource_dir;

将第一个值resource_dir分配给未初始化的指针resource_directory,它相当于

resource_directory[0] = resource_dir[0];

这显然不是你想要的。

您需要指定指针

resource_directory = resource_dir;

但你不应该使用全局变量,特别是

  1. 不要malloc()它,您必须free()所有malloc()和全局变量使其变得困难。

  2. 不要将malloc()用于固定大小的对象,而是将其声明为具有适当大小的数组,如下所示

    char resource_directory[37];
    
  3. 使用strcpy()复制字符串,而不是自行编写循环

    for(int i = 0; i < 25; i++)
     {
        resource_dir[i] = basePath[i];
     }
    

    woule be

    strcpy(resource_dir, basePath);
    
  4. 使用像这样的全局变量时,您应该注意的一件事是,如果您多次致电getResourcesPath(),那么如果必须使用,您将会泄漏资源全局变量承载只要整个程序存在就需要生存的值,尝试使它们的初始化静态,并且你可以完全避免使用全局变量,因为你在{{1的堆栈框架中声明和初始化的所有东西将与程序具有相同的生命周期,因此您可以将它作为参数传递给任何需要它们的函数main(),如果您有许多这些变量,创建一个结构来保存它们,并传递在需要这些资源的函数中,这是一种非常常见的技术。

答案 1 :(得分:0)

此陈述

SDL_Log("%d, %d", &resource_directory, &resource_dir);

以全局变量resource_directory和局部变量resource_dir的地址作为整数值输出。当然他们的地址不同。

至于这句话

*resource_directory = *resource_dir;

然后它将resource_dir指向的字符串的第一个字符存储在指针resource_directory中存储的地址中。但是最初resource_directory被初始化为零作为具有静态存储持续时间的对象。所以程序有不确定的行为。

我认为你的意思是以下

resource_directory = resource_dir;

那就是你希望resource_directory指向函数中内置的字符串。

使用陈述

是没有意义的
free(resource_dir); <--- If I free here the value goes to crud

这个案例陈述中的遗言

resource_directory = resource_dir;

也没有意义。

如果resource_directory需要指向内置的函数字符串,那么你就不应该销毁它。

考虑到使用幻数37和25会使程序不清晰且容易出错。

答案 2 :(得分:0)

指针是一个变量,它包含一个恰好是内存位置地址的数值。例如,NULL指针是一个包含值0的变量。分配&#34; isa指针&#34;的概念。 to是一种通知编译器您的预期用途的方法:也就是说,您不能在非指针变量上使用指针语法。但是在你使用指针语法之前,它们或多或少都像普通变量一样。

int i = 0;
int* p = &i;

int j;
int* q;

j = i; // j has the same value as i
q = p; // q has the same value as p

在上述代码的末尾,pq指向同一地址。我们只想在取消引用指针时使用*语法:

q = p;
*q = *p; // copies the `int` pointed to by `p` to
// the `int` memory location pointed to by `q`,
// which is the same location.

请注意,可以嵌套指针:

int** pp = &p;

pint*,因此&pint**

pp是一个数值,它是包含int*的内存位置的地址。 *pp表示fetch the value at the memory location contained in pp,它将检索第二个数值 - p中的值,它本身是int*,因此是第二个地址。 **pp将检索p指向的整数。

您的作业

*resource_directory = *resource_dir;

复制指向的值,而不是地址。

由于您已将问题标记为C ++,我将通过提供此替代实现来结束:

std::string resource_dir;
void getResourcePath()
{
    char *basePath = SDL_GetBasePath();
    resource_dir = base_path;
    resource_dir += "resources/";
    free(basePath);
}

如果您随后需要resource_dir的c-string值,请使用resource_dir.c_str()

或者,如果您需要C实现:

char* resource_dir;
void getResourcePath()
{
    const char subPath[] = "resources/";
    size_t length;
    char *basePath = SDL_GetBasePath();
    if (resource_dir)
        free(resource_dir);
    length = strlen(basePath) + sizeof(subPath);
    resource_dir = (char*)malloc(length);
    snprintf(resource_dir, length, "%s%s", basePath, subPath);
    free(basePath);
}