在 64 位转换中解决从不同大小的整数转换为指针的错误 [英] Resolving cast to pointer from integer of different size error in 64-bit conversion

查看:41
本文介绍了在 64 位转换中解决从不同大小的整数转换为指针的错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在努力将 PTHotKeyLib 修改为 64 位友好,但我已经运行进入我不知道如何解决的代码问题.在 PTHotKeyCenter 中,registerHotKey 方法创建一个 EventHotKeyID 实例,然后将 PTHotKey 对象的 填充到 id 属性中.原来的代码用了很久.我根据 Apple 的 64 位编程指南将其转换为 NSInteger.

 - (BOOL)registerHotKey:(PTHotKey *)theHotKey {OS状态错误;EventHotKeyID hotKeyID;EventHotKeyRef carbonHotKey;NSValue *key = nil;if ([[self allHotKeys] containsObject:theHotKey])[self unregisterHotKey:theHotKey];if (![[theHotKey keyCombo] isValidHotKeyCombo])返回是;hotKeyID.signature = kHotKeySignature;hotKeyID.id = (NSInteger)theHotKey;...//休息不相关}

当用户触发热键时,它会调用 sendCarbonEvent: 方法,该方法将尝试从 EventHotKeyID 中拉出 PTHotKey 实例.它在 32 位环境下工作,但是在针对 64 位进行编译时,它给出了从不同大小的整数转换为指针"警告

- (OSStatus)sendCarbonEvent:(EventRef)event {OS状态错误;EventHotKeyID hotKeyID;SGHotKey *热键;NSAssert(GetEventClass(event) == kEventClassKeyboard, @"Unknown event class");错误 = GetEventParameter(事件,kEventParamDirectObject,typeEventHotKeyID,零,大小(EventHotKeyID),零,&hotKeyID);如果(错误)返回错误;NSAssert(hotKeyID.signature == kHotKeySignature, @"Invalid hot key id" );NSAssert(hotKeyID.id != 0, @"Invalid hot key id");hotKey = (SGHotKey *)hotKeyID.id;//警告:从不同大小的整数转换为指针//省略其余代码}

从 x86_64 切换回 i386 会删除警告,并且所有内容均已编译并正常运行.在 x86_64 下它会导致崩溃,我不知道如何解决这个问题.关于如何解决它的任何建议?

解决方案

不建议在指针和整数之间进行转换,因为这会导致代码不可移植.

您正在做的事情会导致 C99 定义为未定义行为".这基本上意味着它可能有效,也可能无效.C 语言以让您做这样的事情而闻名,因为它隐含地假设您在输入时知道自己在做什么,并且您拥有 37337 疯狂的技能和多年的经验,知道什么时候做这样的事情是安全的这个和什么时候不是.

可以肯定地说,这是安全的时期之一.

从上下文来看,问题可能是由于将 64 位指针转换为 int 大小的变量.Mac OS X 64 位 ABI 就是所谓的 LP64,这意味着 longs 和 pointers 是 64 位宽,并且int 是 32 位宽.所以,简而言之,在你的一个 pointerint 和返回的转换过程中,你砍掉了前 32 位,这恰好是非常重要的.>

查看文档,id 的类型是 UInt32.因此,简短的回答是您不能将 64 位指针放入 32 位大小的整数.

I'm working on modifying the PTHotKeyLib to be 64-bit friendly, but I've run into an issue in the code that I'm not sure how to get around. In PTHotKeyCenter, the registerHotKey method create an EventHotKeyID instance and then stuffs the of PTHotKey object into the id attribute. The original code used a long. I converted it to NSInteger per Apple's 64 bit programming guide.

  - (BOOL)registerHotKey:(PTHotKey *)theHotKey {
  OSStatus error;
  EventHotKeyID hotKeyID;
  EventHotKeyRef carbonHotKey;
  NSValue *key = nil;

  if ([[self allHotKeys] containsObject:theHotKey])
    [self unregisterHotKey:theHotKey];

  if (![[theHotKey keyCombo] isValidHotKeyCombo])
    return YES;

  hotKeyID.signature = kHotKeySignature;
  hotKeyID.id = (NSInteger)theHotKey;
  ... //Rest is not relevant
  }

When a user triggers the hot key, it calls the sendCarbonEvent: method that will try to pull the PTHotKey instance out of EventHotKeyID. It worked in 32-bit land, but when compiling against 64-bit, it gives a "cast to pointer from integer of different size" warning

- (OSStatus)sendCarbonEvent:(EventRef)event {
  OSStatus error;
  EventHotKeyID hotKeyID;
  SGHotKey *hotKey;

  NSAssert(GetEventClass(event) == kEventClassKeyboard, @"Unknown event class");

  error = GetEventParameter(event,
                            kEventParamDirectObject, 
                            typeEventHotKeyID,
                            nil,
                            sizeof(EventHotKeyID),
                            nil,
                            &hotKeyID);
  if (error)
    return error;

  NSAssert(hotKeyID.signature == kHotKeySignature, @"Invalid hot key id" );
  NSAssert(hotKeyID.id != 0, @"Invalid hot key id");

  hotKey = (SGHotKey *)hotKeyID.id; // warning: cast to pointer from integer of different size
// Omitting the rest of the code
} 

Switching from x86_64 back to i386 removes the warning and everything compiled and runs properly. Under x86_64 it causes a crasher, and I'm not sure how to get around that issue. Any suggestions on how to resolve it?

解决方案

Casting between pointers and integers is not recommended because it results in non-portable code.

What you are doing results in what C99 defines as "undefined behavior". This basically means it might work, and it might not. The C language is famous for letting you do things like this because it implicitly assumes that you knew what you were doing when you typed it in and that you have the wizardly 37337 mad skillz and years of experience to know when it's safe to do something like this and when it's not.

It's safe to say this this is one of those times when it was not safe to do.

The problem, from context, is probably due to casting a 64-bit pointer in to an int sized variable. Mac OS X 64-bit ABI is what is known as LP64, which means that longs and pointers are 64-bits wide, and that ints are 32-bits wide. So, in short, during one of your pointer to int and back again castings, you chopped off the top 32 bits, which just so happened to be really important.

Looking at the docs, the type for id is UInt32. So, the short answer is you can't put 64-bit pointers in to 32-bit sized integers.

这篇关于在 64 位转换中解决从不同大小的整数转换为指针的错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆