我正在尝试通过首先将字符串初始化到随后从那里读取文件的位置来设置来自c程序的本地文件夹访问。我最终还需要以类似的方式编写文件,但是我遇到了一些奇怪的错误。
首先是代码: resource_utils.h
static char* res_dir = NULL;
void clearnUpResourcePath(void);
char* getResource(char* filename);
char* readFile(char* file_path);
void writeFile(filename, File* file);
resource_utils.c
#include "resource_utils.h"
static char* getBasePath(void);
static void initResourcePath(void);
char* getResource(char* filename)
{
if(res_dir == NULL)
{
initResourcePath();
}
printf("res dir: %s || fn:%s\n",res_dir, filename);
char* str = (char*)malloc(sizeof(char) + strlen(res_dir) + strlen(filename));
memcpy(str, res_dir, strlen(res_dir)+1);
memcpy(str + strlen(res_dir), filename, strlen(filename));
str[(strlen(filename) + strlen(res_dir))] = '\0';
printf("resource filename:%s\n\n",str);
return str;
}
static void initResourcePath(void) {
char *base_path = getBasePath();
size_t len = strlen(base_path) + 22;
size_t i = 0;
size_t sz = 0;
char tmp[len];
while(base_path[i] != '\0')
{
if(base_path[i] == 'b' && base_path[i+1] == 'i' && base_path[i+2] == 'n')
{
sz = i;
}
tmp[i] = base_path[i];
i++;
}
char* b = strstr(tmp, "/bin");
memcpy(b, "/bin/resources/",15);
tmp[ sz + 14 ] = '\0';
res_dir = (char*)malloc(sizeof(char) * (sz + 4));
i = 0;
while(tmp[i] != '\0')
{
res_dir[i] = tmp[i];
i++;
}
res_dir[i] = '\0';
free(base_path);
}
void clearnUpResourcePath(void)
{
free(res_dir);
}
static char* getBasePath(void)
{
return "string to working directory"
}
char* readFile(char* file_path)
{
FILE* fp = fopen(file_path, "r");
if( fp == NULL )
{
perror("Error while opening the file.\n");
printf("failed to open file path:%s\n",file_path);
exit(EXIT_FAILURE);
}
size_t size = 1024;
char ch;
int index = 0;
char* line = (char*)malloc(sizeof(char) * size);
while( (ch = (char)fgetc(fp)) != EOF )
{
*(line+index) = ch;
++index;
if(index == size-1)
{
size = size * 2;
line = realloc(line, size);
printf("\nreallocing %zu\n",size);
}
line = realloc(line, (sizeof(char) * index) + 1);
*(line+index) = '\0';
}
//printf("sanity check\n\n%d\n\n",strlen(line));
//printf("final size: %lu for loading: %s\n",strlen(line), file_path);
fclose(fp);
return line;
}
这基本上是假设设置此资源路径一次,在程序的生命周期内保留它并在程序退出之前释放它,但有时会得到一些奇怪的结果。
看一下这个输出
char* vshad = getResource("vert.shad");
char* fshad = getResource("frag.shad");
char* name = getResource("pal.ppm");
char* name1 = getResource("1234pal.ppm");
char* name2 = getResource("pal.ppm1234");
char* name3 = getResource("pal1.ppm");
char* name4 = getResource("pal.pp");
char* name5 = getResource("pal.ppdddddm");
char* name6 = getResource("pa");
res dir: /Users/username/DIRECTORY/project/build/bin/resources/ || fn:vert.shad
res dir len:48, filename len:9
resource filename:/Users/username/DIRECTORY/project/build/bin/resources/vert.shad
res dir: /Users/username/DIRECTORY/project/build/bin/resources/ || fn:frag.shad
res dir len:48, filename len:9
resource filename:/Users/username/DIRECTORY/project/build/bin/resources/frag.shad
res dir: /Users/username/DIRECTORY/project/build/bin/resources/FACETKEYS || fn:pal.ppm
res dir len:57, filename len:7
resource filename:/Users/username/DIRECTORY/project/build/bin/resources/FACETKEYSpal.ppm
res dir: /Users/username/DIRECTORY/project/build/bin/resources/FACETKEYS || fn:1234pal.ppm
res dir len:57, filename len:11
resource filename:/Users/username/DIRECTORY/project/build/bin/resources/FACETKEYS1234pal.ppm
res dir: /Users/username/DIRECTORY/project/build/bin/resources/FACETKEYS || fn:pal.ppm1234
res dir len:57, filename len:11
resource filename:/Users/username/DIRECTORY/project/build/bin/resources/FACETKEYSpal.ppm1234
res dir: /Users/username/DIRECTORY/project/build/bin/resources/FACETKEYS || fn:pal1.ppm
res dir len:57, filename len:8
resource filename:/Users/username/DIRECTORY/project/build/bin/resources/FACETKEYSpal1.ppm
res dir: /Users/username/DIRECTORY/project/build/bin/resources/FACETKEYS || fn:pal.pp
res dir len:57, filename len:6
resource filename:/Users/username/DIRECTORY/project/build/bin/resources/FACETKEYSpal.pp
res dir: /Users/username/DIRECTORY/project/build/bin/resources/FACETKEYS || fn:pal.ppdddddm
res dir len:57, filename len:12
resource filename:/Users/username/DIRECTORY/project/build/bin/resources/FACETKEYSpal.ppdddddm
res dir: /Users/username/DIRECTORY/project/build/bin/resources/FACETKEYS || fn:pa
res dir len:57, filename len:2
resource filename:/Users/username/DIRECTORY/project/build/bin/resources/FACETKEYSpa
loaded name:/Users/username/DIRECTORY/project/build/bin/resources/FACETKEYSpal.ppm?
前两个调用正确加载但后续调用,特别是如果我更改文件名的长度会导致代码中断。我不太确定。
我也注意到我的res_dir的长度发生了变化,我真的不明白。
以及接受的答案,这是我的新代码,没有魔术数字
static void initResourcePath(void)
{
char *base_path = getBasePath();
size_t len = strlen(base_path) *2; //making enough space
size_t i, sz = 0;
char tmp[len];
while(base_path[i] != '\0')
{
if(base_path[i] == 'b' && base_path[i+1] == 'i' && base_path[i+2] == 'n')
{
sz = i;
}
tmp[i] = base_path[i];
i++;
}
char* b = strstr(tmp, "/bin");
memcpy(b, "/bin/resources/",15);
tmp[ sz + 14 ] = '\0';
res_dir = (char*)malloc(sizeof(char) * (strlen(tmp) +1));
strcpy(res_dir, tmp);
free(base_path);
}
答案 0 :(得分:1)
您遇到的问题是:
res_dir = (char*)malloc(sizeof(char) * (sz + 4));
您没有分配足够的空间。您可能打算使用sz + 14
代替sz + 4
。这是使用魔术数字的问题之一,如WhozCraig所述。
您知道自己正在将tmp
复制到res_dir
,而不是做那样令人费解的事情,所以请改为:
res_dir = malloc(strlen(tmp)+1);
请注意,malloc
的返回值未被投放。如果你没有#include <stdlib.h>
,那么在C中这样做可以隐藏微妙的错误。