https://i.loli.net/2018/09/11/5b977fcb2e371.png
赋值之后:
https://i.loli.net/2018/09/11/5b977fcb3515e.png
func_name 为字符串"wait", 但是赋值之后却不是这个值
相关声明如下:
typedef struct _local_func {
const char *func_name; // function name
lua_CFunction func_ptr; // function pointer
const char *help_info; // help information for this function
} LOCAL_FUNC;
LOCAL_FUNC g_local_func;
不好意思,g_local_func是一个array,笔误。
LOCAL_FUNC g_local_func[];
//context here
bool init_plugins(lua_State* L){
//...
const char* func_name = g_local_func[i].func_name;
lua_CFunction func_pt = g_local_func[i].func_ptr;
const char* help_info = g_local_func[i].help_info;
}
我在c代码中定义了一个g_local_func结构体数组,然后定义了一个init_plugins方法,在c中调用这个方法时如上面图片所示,g_local_func是有值的,但是赋值给函数中的局部变量的时候,却无法正确获取到值。
这个跟lua通过栈来传递参数应该没有关系吧,因为我是在c中调用的这个函数,g_local_func是一个全局的变量。
我把代码提取了一下。希望大佬解惑。
file: TestStudent.cpp
#include "stdafx.h"
#include "TestStudent.h"
extern const int NUM;
extern Student allStudents[];
void print_student(){
for (int i = 0; i < NUM; ++i){
auto first_name = allStudents[i].first_name; //not working, why?
auto last_name = allStudents[i].last_name; //last_name is NULL?
std::cout << first_name << " " << last_name << std::endl;
}
}
int _tmain(int argc, _TCHAR* argv[])
{
print_student();
return 0;
}
file: source.cpp
#include "stdafx.h"
#include "TestStudent.h"
const int NUM = 3;
static Student* get_all_students(){
Student* ss = new Student[NUM];
Student* ptr = ss;
for (int i = 0; i < NUM; ++i){
ptr->first_name = "test1";
ptr->last_name = "test2";
++ptr;
}
return ss;
}
Student* allStudents = get_all_students();
file: TestStudent.h
#pragma once
typedef struct _student{
const char* first_name;
const char* last_name;
} Student;
extern const int NUM;
1
Dori 2018-09-11 17:32:00 +08:00
踩踩
|
2
coderluan 2018-09-11 17:35:43 +08:00
->
|
3
raysonx 2018-09-11 19:00:34 +08:00 via Android
代码看起来没有问题,不过我好奇的是 g_local_func 看起来是一个结构体变量,你是怎么应用下标的?
|
4
kljsandjb 2018-09-11 19:41:39 +08:00 via iPhone
上下文感觉不够啊…看不出来,还有 g_local_func 是个结构体数组?不一样至少说明 func_name 指向的内存被破坏了吧?看看栈有没有被破坏或者如果你是分配在堆上的话,是不是内存管理出了问题😂
|
5
bp0 2018-09-11 21:49:33 +08:00
g_local_func 不是数组吧,怎么看都只是一个全局变量而已。去掉[i]试试看。
|
6
si 2018-09-11 22:07:16 +08:00
猜不到是怎么赋值的
|
7
inoki 2018-09-11 22:22:22 +08:00 via Android
lua interpreter 源代码?
|
8
Deville 2018-09-11 23:38:55 +08:00 via iPhone
只能看得出是 vs 2017....
|
9
zyp0921 2018-09-12 09:03:31 +08:00
这是 C 语言吧
|
11
v2byy OP @kljsandjb 恩,我是通过 malloc 来给 g_local_func 分配的内存,是这样的,我使用在 c 文件中声明并给 g_local_func 分配内存,然后在另外一个 c 文件中通过 extern 导入 g_local_func 变量,然后调用的这个方法。
|
15
wutiantong 2018-09-12 09:33:56 +08:00
@v2byy 看起来不会有你所说的“赋值不对”的问题,建议你直接 printf(%s, %p)出来看看?
|
16
tusj 2018-09-12 09:38:37 +08:00
感觉是乌龙
|
17
ipwx 2018-09-12 10:07:43 +08:00 via iPhone
用 *g_local_func
|
18
raysonx 2018-09-12 10:47:51 +08:00
从楼主给出的上下文中看不出任何问题,怀疑:
1. 调试器故障。 2. 编译器故障。 3. 多线程运行,全局数组被覆盖。 |
21
innoink 2018-09-12 16:35:57 +08:00 via Android 1
你把 extern Student allStudents[]改成 extern Students* allStudents
|
22
kidtest 2018-09-12 16:44:58 +08:00 1
file: TestStudent.cpp
#include "stdafx.h" #include "TestStudent.h" extern const int NUM; extern Student allStudents[]; 最后一行修改为:extern Student* allStudents 即可。 另外记得释放内存 |
25
innoink 2018-09-12 17:17:29 +08:00 via Android
@v2byy 链接过程是不做类型检查的,你想一下数组和指针变量的区别,指针额外占用一块内存保存地址,你把他声明为数组的话,连接器找到 allStudents 这个符号,会认为这就是数组首地址,即认为这个符号后面的数据就是数组内容。
|
26
innoink 2018-09-12 17:22:40 +08:00 via Android
或者你想一下,如果是真的有个 allStudents[],比如有个 Students allStudents[10],那么你 extern Students allStudents[],和你以前的写法之间的区别。
|
27
gnaggnoyil 2018-09-12 18:29:11 +08:00
您可能是 array to pointer decay 的受害者
|
28
raysonx 2018-09-12 18:37:23 +08:00 via Android
@innoink 但这并不能解释为何那条本地变量的的赋值结果会发生变化。我怀疑是因为调试器解析符号的行为和链接器实际链接的行为不一致,导致调试器里看到的=后面的值是错误的。
|
30
v2byy OP @raysonx 是不是其实调试器显示的 allStudent[i].first-name 其实是错的,赋值操作其实是对的
|
31
raysonx 2018-09-12 19:16:39 +08:00
@v2byy 我的理解是:
不能简单的说对不对吧。大概就是 allStudents 的声明和实现不一致(声明为数组,实际为指针)。 调用方( TestStudent.cpp )只能看到头文件,看不到具体实现,把 allStudents 当成了数组,于是 allStudents[i]被编译为了指针的值向后偏移,即*(allStudents + i),造成访问越界。 调试器的行为目测与编译器不一致,它把 allStudents 视为一个指针,将 allStudents[i]解析为 allStudents 所指向的数组再向后偏移即*(*allStudents + i)。 总而言之,赋值号=后面的求值结果与你从调试器看到不一致。 |
32
raysonx 2018-09-12 19:27:32 +08:00
忽然发现我哦上面 *(allStudents + i)和*(*allStudents + i)的写法也是有歧义的。我也恨死 array to pointer decay 这个特性了。应当把 allStudents 替换 source.cpp 中那个全局指针变量的地址。
|
33
innoink 2018-09-12 20:36:01 +08:00
调试器没有链接步骤,是按照语法树来的,找到 allStudents 所在的编译单元,从它的语法树找到类型
真正到了链接步骤,语法树已经没了 |
34
kljsandjb 2018-09-13 12:42:08 +08:00 via iPhone
看到你贴的代码了,指针变量的值是你需要的,你这样 extern 的话,就是这个变量本身了。数组可以退化成指针,那这个指针指向的是数组首地址,但是指针转为数组的话,这个时候,你 focus 的地方应该是这个指针指向的内存位置,而不是这个指针本身在内存的位置。
|
35
kljsandjb 2018-09-13 12:55:01 +08:00 via iPhone 1
举个例子,int arr[N];这是个数组定义,然后 int *p = arr, 这个时候 p 指向的是数组首地址。强行转为 p[]的话,那这个 p 你希望是转换之前 p 指向的位置的地址,这样就显然矛盾了:)
|
36
bp0 2018-09-13 14:03:01 +08:00 2
数组可以退化成指针,指针不能进化成数组。
借用 @kljsandjb #35 的例子。 数组的名称“ arr ”就是数组的第一个元素的地址,编译器并不会给“ arr ”额外分配一个地址。而指针“ p ”本身是要占用一个地址空间的,“ p ”的地址空间中保存的内容是数组“ arr ”的首地址。 当编译器编译 TestStudent.cpp 文件时,会按照数组的方式直接使用“ allStudents ”的地址作为组数的首地址。而在编译 source.cpp 时,会给指针“ allStudents ”分配一个地址,并让其指向你动态分配的数组的首地址。 所以 TestStudent.cpp 文件中实际上是把指针“ allStudents ”的地址当成数组的首地址使用了,自然得不到正确的内容。 那为什么调试器能看到正确的内容呢?因为调试器是解析的 elf 文件中的 debug 信息。在 debug 信息中 allStudents 就是一个指针而不是一个数组。所以可以读到正确的内容。 |