我一直在尽力学习C++,但我之前的培训在一个主要问题上不足:内存管理.我的主要语言都有自动垃圾收集,所以跟踪一切从来没有真正必要.我已经尝试过在线阅读C++中的内存管理,但我对此感到怀疑,因为我遗漏了一些东西.
所以,这是一个多部分的问题:
delete在循环重新迭代之前调用任何新指针.它是否正确?你需要用引用做些什么吗?mallocfreecallocrealloc***********************更新*******************
这是为了解释在评论一中对lmgtfy的引用(由Ewan提供).如果您开始阅读那里可用的信息,则对初学者没用.我认为这是一个伟大的理论,但它对这个问题既不相关也不有用.
我已经看过其他答案,但似乎无法让这个工作.我正在尝试调用DLL中的函数来与SMBus设备进行通信.该函数接受一个结构的指针,该结构有一个数组作为其中一个字段.所以...
在C:
typedef struct _SMB_REQUEST
{
unsigned char Address;
unsigned char Command;
unsigned char BlockLength;
unsigned char Data[SMB_MAX_DATA_SIZE];
} SMB_REQUEST;
Run Code Online (Sandbox Code Playgroud)
我想我必须在DLL填充数据数组时设置Address,Command和BlockLength的值.需要此结构的函数将其作为指针
SMBUS_API int SmBusReadByte( SMBUS_HANDLE handle, SMB_REQUEST *request );
Run Code Online (Sandbox Code Playgroud)
所以我在Python中设置了这样的结构:
class SMB_REQUEST(ctypes.Structure):
_fields_ = [("Address", c_char),
("Command", c_char),
("BlockLength", c_char),
("Data", type(create_string_buffer(SMB_MAX_DATA_SIZE))]
Run Code Online (Sandbox Code Playgroud)
*注意:我也尝试过数据类型的ctypes.c_char*SMB_MAX_DATA_SIZE*
要将指向此类型结构的指针传递给函数,我首先尝试将其初始化,如下所示:
data = create_string_buffer(SMB_MAX_DATA_SIZE)
smb_request = SMB_REQUEST('\x53', \x00', 1, data)
Run Code Online (Sandbox Code Playgroud)
这回应:
TypeError: expected string or Unicode object, c_char_Array_32 found
Run Code Online (Sandbox Code Playgroud)
如果我尝试省略数据数组,如下所示:
smb_request = SMB_REQUEST('\x53', \x00', 1)
Run Code Online (Sandbox Code Playgroud)
不,错误.但是,当我尝试将此传递给函数时:
int_response = smbus_read_byte(smbus_handle, smb_request))
Run Code Online (Sandbox Code Playgroud)
我明白了:
ArgumentError: argument 2: <type 'exceptions.TypeError'>: expected …Run Code Online (Sandbox Code Playgroud) 考虑一下:
void* x = &x;
printf("%p\n", x);
Run Code Online (Sandbox Code Playgroud)
令人惊讶的是,它编译并运行输出:
7ffb2f7248
在尚未创建的情况下如何x获取自身的地址x?
编辑:请注意,在这种情况下,关于它的分配没有歧义,明确提出质疑的内容。
我正在浏览“Rust Book”网站,以便学习即将到来的工作面试的语言。在向量章节中,有两个代码示例:
fn main() {
let v = vec![100, 32, 57];
for i in &v {
println!("{}", i);
}
}
Run Code Online (Sandbox Code Playgroud)
和:
fn main() {
let mut v = vec![100, 32, 57];
for i in &mut v {
*i += 50;
}
}
Run Code Online (Sandbox Code Playgroud)
现在我想知道,为什么对于第一个样本,当我们将对向量元素i的引用传递到:
println!("{}", i);
但是在我们向向量的每个元素添加 50 的示例中,在添加到 50 之前,我们必须使用 * 取消引用该元素?
我们为什么不/不能做以下事情:
fn main() {
let v = vec![100, 32, 57];
for i in &v {
println!("{}", *i); // why don't we have to dereference before we …Run Code Online (Sandbox Code Playgroud) 是否有一种有保证的(不是实现定义的!)方法来检查指针对齐?
查询指针对齐的最常见方法似乎是:
bool is_aligned(void const *ptr, size_t alignment) {
return reinterpret_cast<intptr_t>(ptr) % alignment == 0;
}
Run Code Online (Sandbox Code Playgroud)
例如,这就是Boost.Align 检查对齐方式的方式。
然而,至少在 C++17 中,basic.compound#3.4说:
指针类型的值表示是实现定义的。
指针可以显式转换为任何足够大以容纳它的整型。映射函数是实现定义的。
(例如)将指针表示为具有相反位顺序的整数似乎是合法的,在这种情况下,上面的简单算术将不起作用。
AFAICT,我们可以检查对齐的唯一有保证的方法是使用std::align,如果自由地阅读(我确信这是对 的滥用std::align),可以像这样使用:
bool is_aligned(void const *ptr, size_t alignment) {
void *mut_ptr = const_cast<void *>(ptr);
size_t space = alignment;
return std::align(alignment, alignment, mut_ptr, space) == ptr;
}
Run Code Online (Sandbox Code Playgroud)
然而,在绝大多数平台上,指针只是奇特的整数,或者我希望 Boost 有一个代码路径。是否有任何平台(除了 ds9k :P)其中指针不仅仅是花哨的整数?
通过标准化“应具有与”或“如果与”对齐reinterpret_cast<intptr_t>(ptr)相同的对象表示,我们会损失什么?似乎这些都不会排除分段内存或具有陷阱表示的指针,这是我能想到的两种非典型情况。ptrreinterpret_cast<intptr_t>(ptr) % alignment == 0ptr …
我有一个Derived直接从两个基类继承的类,Base1和Base2.我想知道一般来说,将指针与基类进行比较以确定它们是否是同一个Derived对象是否安全:
Base1* p1;
Base2* p2;
/*
* Stuff happens here. p1 and p2 now point to valid objects of either their
* base type or Derived
*/
//assert(p1 == p2); //This is illegal
assert(p1 == static_cast<Base1*>(p2)); //Is this ok?
assert(static_cast<Derived*>(p1) == static_cast<Derived*>(p2)); //How about this?
Run Code Online (Sandbox Code Playgroud)
指针保证有效,但不一定指向Derived对象.我的猜测是这可能很好,但我想从技术C++的角度来看它是否可以.我实际上从不对指针进行任何操作,我只是想知道它们是否指向同一个对象.
编辑:如果我可以保证p1并p2指向Derrived对象似乎是安全的.我基本上想知道如果它们不是 - 如果一个或两个都指向基础对象,它是否安全,那么比较是否必然会失败?同样,我可以保证指针有效(即,p1永远不会指向Base2对象,反之亦然)
我正试图通过玩家手牌迭代.
Player.cpp
vector<Card*>::iterator iter;
for(iter = current_cards.begin(); iter != current_cards.end(); iter++) {
cout << iter->display_card() << endl;
}
Run Code Online (Sandbox Code Playgroud)
它在
cout << iter->display_card() << endl;
Run Code Online (Sandbox Code Playgroud)
目前提出"错误:表达式必须具有指针类型".
同样,current_cards声明为:
vector<Card*>current_cards;
Run Code Online (Sandbox Code Playgroud)
此外,display_card()方法很简单:
Card.cpp
string Card::display_card(){
stringstream s_card_details;
s_card_details << "Colour: " << card_colour << "\n";
s_card_details << "Type: " << card_type << "\n";
return s_card_details.str();
}
Run Code Online (Sandbox Code Playgroud)
我已经查看了各种资源,并且针对类似问题提出的所有建议都没有对我有用.谢谢你的帮助!
我在讲座中被教过,free()两次拨打指针真是非常糟糕.我知道NULL在释放它之后立即设置指针是一种很好的做法.
但是,我仍然没有听到任何解释为什么会这样.根据我的理解,方式malloc()有效,它应该在技术上跟踪它已经分配的指针并让你使用.那么为什么它不知道它接收到的指针是否free()已被释放?
当你打电话free()给以前已经被释放的位置时,我很乐意理解,内部会发生什么.
希望这不是一个愚蠢的问题,但我试图围绕汇编指针.
究竟有什么区别:
mov eax, ebx
Run Code Online (Sandbox Code Playgroud)
和
mov [eax], ebx
Run Code Online (Sandbox Code Playgroud)
何时应该dword ptr [eax]使用?
另外,当我尝试这样做时,mov eax, [ebx]我得到一个编译错误,为什么会这样?