读代码时,写测试代码验证自己的想法
这两天为了编译ruby0.49,可是费尽了心思。
后来,发现,为了再现编译中的错误,最好是自己写测试代码。
一。gdbm调试
因为ruby049中有一个文件dbm.c,为了编译它,需要安装gdbm。从来没有用过dbm。于是在网上学安装,并在网上找文件,再进行编译,等本地小程序编译后,再修改Makefile,dbm.c
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
//#include "/usr/include/gdbm/ndbm.h"
// On some systems you need to replace the above with
#include <gdbm-ndbm.h>
#include <string.h>
#define TEST_DB_FILE "/tmp/dbm1_test"
#define ITEMS_USED 3
/* A struct to use to test dbm */
struct test_data {
char misc_chars[15];
int any_integer;
char more_chars[21];
};
int main() {
struct test_data items_to_store[ITEMS_USED];
struct test_data item_retrieved;
char key_to_use[20];
int i, result;
datum key_datum;
datum data_datum;
DBM *dbm_ptr;
dbm_ptr = dbm_open(TEST_DB_FILE, O_RDWR | O_CREAT, 0666);
if (!dbm_ptr) {
fprintf(stderr, "Failed to open database\n");
exit(EXIT_FAILURE);
}
/* put some data in the structures */
memset(items_to_store, '\0', sizeof(items_to_store));
strcpy(items_to_store[0].misc_chars, "First!");
items_to_store[0].any_integer = 47;
strcpy(items_to_store[0].more_chars, "foo");
strcpy(items_to_store[1].misc_chars, "bar");
items_to_store[1].any_integer = 13;
strcpy(items_to_store[1].more_chars, "unlucky?");
strcpy(items_to_store[2].misc_chars, "Third");
items_to_store[2].any_integer = 3;
strcpy(items_to_store[2].more_chars, "baz");
for (i = 0; i < ITEMS_USED; i++) {
/* build a key to use */
sprintf(key_to_use, "%c%c%d",
items_to_store[i].misc_chars[0],
items_to_store[i].more_chars[0],
items_to_store[i].any_integer);
/* build the key datum strcture */
key_datum.dptr = (void *)key_to_use;
key_datum.dsize = strlen(key_to_use);
data_datum.dptr = (void *)&items_to_store[i];
data_datum.dsize = sizeof(struct test_data);
result = dbm_store(dbm_ptr, key_datum, data_datum, DBM_REPLACE);
if (result != 0) {
fprintf(stderr, "dbm_store failed on key %s\n", key_to_use);
exit(2);
}
} /* for */
/* now try and retrieve some data */
sprintf(key_to_use, "bu%d", 13); /* this is the key for the second item */
key_datum.dptr = key_to_use;
key_datum.dsize = strlen(key_to_use);
data_datum = dbm_fetch(dbm_ptr, key_datum);
if (data_datum.dptr) {
printf("Data retrieved\n");
memcpy(&item_retrieved, data_datum.dptr, data_datum.dsize);
printf("Retrieved item - %s %d %s\n",
item_retrieved.misc_chars,
item_retrieved.any_integer,
item_retrieved.more_chars);
}
else {
printf("No data found for key %s\n", key_to_use);
}
dbm_close(dbm_ptr);
exit(EXIT_SUCCESS);
}
编译命令如下
gcc t1.c -lgdbm -lgdbm_compat
yang@DESKTOP-V9HS3B6:~/ruby049$
为了搞这个gdbm,我至少折腾了两天。甚至想去读gdbm的源码。
二。指针相关错误
我开始以为是指针类型相关错误,如
#include<stdio.h>
#include<stdlib.h>
int main()
{
struct fu {
int num;
};
struct zi {
struct fu obj_fu;
int key;
};
struct zi obj_zi;
struct fu *q=(struct fu *) malloc(sizeof(struct zi));
printf("ok\n");
return 0;
}
以为,父类型的指针比子类型的大。于是写测试程序。结果可以通过。所以问题,不在这儿。
在网上找资料后,发现
#include<stdio.h>
void test()
{
int n=10;
(void *)n;
}
int main()
{
test();
return 0;
}
这样,居然就重现了错误。因为64位的指针值的24位整数,而32位的好像是16位。于是就再转一下。
#include<stdio.h>
void test()
{
int n=10;
(void *)(long)n;
}
int main()
{
test();
return 0;
}
gcc t2.c
yang@DESKTOP-V9HS3B6:~/ruby049$ ./a.out
ok
从昨天开始,我为了去年1万多条警告,就不停的加(long)
#include<stdio.h>
int main()
{
int a=10;
printf("%p",&a);
return 0;
}
这是为了打印地址的值。
gcc t4.c
yang@DESKTOP-V9HS3B6:~/ruby049$ ./a.out
0x7fffc4a4b89cyang@DESKTOP-V9HS3B6:~/ruby049$
但费尽这么多,执行程序时,还是报错误。只能打印出版本号。