Objective-C 中 int 数组实例变量中的奇怪值

发布于 2024-12-13 09:36:23 字数 1786 浏览 1 评论 0原文

我寻找了类似的主题,但到目前为止还没有运气,所以这里是:

在 Objective-C 类中,我声明了一个 int 指针实例变量来保存 int 数组:

@interface MyList : NSObject {
    int index;      // A simple int to hold an index reference
    NSString *name; // The name of the list
    int *bookList;  // A pointer to an int array that holds a list of numbers
}

@property (nonatomic) int index;
@property (nonatomic, copy) NSString *name;
@property (nonatomic) int *bookList;

@end

我对此进行了如下测试,并且实例变量中包含的所有数据均已通过NSLog语句正确存储和显示:

MyList *aList = [[MyList alloc] init];
[aList setIndex:1];
[aList setName:@"ListOne"];
[aList setBookList:(int []){1, 2, 3, 0}];

NSLog(@"Show MyList object's data after object is populated");
NSLog(@"[%d]: %@", aList.index, aList.name);
for (int i = 0; i < 4; i++) {
    NSLog(@"bookList[%d] = %d", i, aList.bookList[i]);
}

但是,当我发送此消息时对象作为方法的参数,我尝试打印该对象的内容int 数组,我得到奇怪的数字,从方法返回后也会发生同样的情况:

-(void)displayMyList:(MyList *)theList {
    NSLog(@"Show MyList object's data in displayMyList method");
    NSLog(@"[%d]: %@", theList.index, theList.name);
    for (int i = 0; i < 4; i++) {
        NSLog(@"bookList[%d] = %d", i, theList.bookList[i]);
    }
}

我不知道我的测试代码出了什么问题,因为 index 的值当对象发送到 displayMyList: 方法时,name 实例变量不会发生更改。我一步步调试,指向 int 数组的指针始终指向同一地址,因此似乎在更改数组值的地方存在副作用,或者我没有了解如何为此类指向 int 数组的指针放置内存。也许这只是我没有得到正确的一些指针算术,因为我没有在我拥有的任何 iPhone 编程书中看到过这一点。

我想实现 int 数组,因为我用它做的数学非常简单,而且使用 NSArray 似乎有点矫枉过正(如果这种方法不起作用,我总是可以不过,请使用 NSArray )。

I looked for similar topics but no luck so far, so here it goes:

In an Objective-C class I declared an int pointer instance variable to hold an array of int:

@interface MyList : NSObject {
    int index;      // A simple int to hold an index reference
    NSString *name; // The name of the list
    int *bookList;  // A pointer to an int array that holds a list of numbers
}

@property (nonatomic) int index;
@property (nonatomic, copy) NSString *name;
@property (nonatomic) int *bookList;

@end

I tested this as follows and all data contained in the instance variables was correctly stored and displayed by the NSLog statements:

MyList *aList = [[MyList alloc] init];
[aList setIndex:1];
[aList setName:@"ListOne"];
[aList setBookList:(int []){1, 2, 3, 0}];

NSLog(@"Show MyList object's data after object is populated");
NSLog(@"[%d]: %@", aList.index, aList.name);
for (int i = 0; i < 4; i++) {
    NSLog(@"bookList[%d] = %d", i, aList.bookList[i]);
}

However, when I send this object as an argument to a method and I try to print the contents of the int array, I get strange numbers, and the same happens after returning from the method:

-(void)displayMyList:(MyList *)theList {
    NSLog(@"Show MyList object's data in displayMyList method");
    NSLog(@"[%d]: %@", theList.index, theList.name);
    for (int i = 0; i < 4; i++) {
        NSLog(@"bookList[%d] = %d", i, theList.bookList[i]);
    }
}

I don't know what's wrong with my test code, as the values of the index and name instance variables don't get changed when the object is sent to the displayMyList: method. I debugged step-by-step and the pointer to the int array points to the same address all the time, so it seems there's a side-effect somewhere that's changing the array's values, or I'm not getting how memory is placed for this type of pointers to int arrays. Maybe it's just some pointer arithmetic I'm not getting right, because I haven't seen this in any of the iPhone programming books I have.

I wanted to implement the int array because the math I do with it is really simple and it seemed using an NSArray was overkill (if this approach doesn't work I can always go with an NSArray, though).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

浪推晚风 2024-12-20 09:36:23

您的问题在于:

[aList setBookList:(int[]){1,2,3,0}];

堆栈分配引用的范围仅限于周围的函数,这就是为什么您在不同的范围内获得垃圾值的原因,因为分配它的堆栈不再使用。

您需要malloc这个int列表来将此引用推送到堆上,如下所示:

int sourceList[] = { 1, 2, 3, 0 }; 
int *bookList = malloc(sizeof sourceList); 

memcpy(aList->bookList, sourceList, sizeof sourceList);

既然您调用了malloc,您最终必须放弃通过在 -dealloc 方法中调用 free 来释放“数组”占用的内存。

作为替代方案,您可以使用 NSNumber 对象的 NSArray,如下所示:

@property (nonatomic, strong) NSArray *bookList;

//...

#define NUMINT(x) [NSNumber numberWithInt:x]

NSArray *bookList = [NSArray arrayWithObjects:NUMINT(1), NUMINT(2), NUMINT(3), NUMINT(0), nil];
[aList setBookList:bookList];

Your problem is here:

[aList setBookList:(int[]){1,2,3,0}];

The scope of a stack-allocated reference is limited only to the surrounding function, that's why you're getting garbage values in a different scope, because the stack in which it was allocated is no longer in use.

You need to malloc this list of ints to push this reference onto the heap, like so:

int sourceList[] = { 1, 2, 3, 0 }; 
int *bookList = malloc(sizeof sourceList); 

memcpy(aList->bookList, sourceList, sizeof sourceList);

Since you called malloc, you must eventually relinquish the memory occupied by the "array" by calling free in your -dealloc method.

As an alternative, you could use an NSArray of NSNumber objects, like so:

@property (nonatomic, strong) NSArray *bookList;

//...

#define NUMINT(x) [NSNumber numberWithInt:x]

NSArray *bookList = [NSArray arrayWithObjects:NUMINT(1), NUMINT(2), NUMINT(3), NUMINT(0), nil];
[aList setBookList:bookList];
吻风 2024-12-20 09:36:23

您在分配数组时创建的数组是该方法的本地数组;方法结束后内存会被重新使用,这意味着那里基本上有垃圾值。指针本身不会改变,因为它是一个 ivar,并且它指向的地址也不会改变,因为你没有重新分配它。仅指向地址的内容发生变化。

如果您希望内存在对象的生命周期内保留下来,您需要自己管理内存。这并不是什么大问题,假设您不需要将数组交给任何其他对象。*如果您已经有使用 的逻辑,则无需切换到 NSArray >int

// Get the memory
// malloc returns a generic C pointer, void *, so the value needs to be
// cast to make the compiler happy. 
int * arr = (int *)malloc(LEN_OF_BOOKLIST * sizeof(int));
// Fill in values
//...
// Assign to the ivar
[aList setBookList:arr];

然后,您需要在对象被销毁时释放该内存:

- (void) dealloc {

    free(bookList);
    // Clean up other ivars
    [super dealloc];
}

总而言之,这非常类似于手动处理任何旧对象的内存。您调用 malloc (带有一个参数,说明您想要的内存量),而不是将 alloc 发送到类(它知道需要多少内存),并使用 free 而不是 release 来放弃内存。 (另请注意,由于没有引用计数,free 会立即标记内存以供重用。)

*这本质上就是发明引用计数的原因。

The array that you're creating when you assign it is local to that method; the memory gets re-used after the method ends, which means that there are basically garbage values ending up there. The pointer itself doesn't change because it's an ivar, and the address it points to doesn't change because you haven't reassigned it. Only the contents of the pointed-to address change.

You'll need to manage the memory yourself if you want it to stick around for the life of your object. This isn't too big a deal, assuming that you won't need to hand off the array to any other object.* There's no need to switch to an NSArray if you already have logic using ints.

// Get the memory
// malloc returns a generic C pointer, void *, so the value needs to be
// cast to make the compiler happy. 
int * arr = (int *)malloc(LEN_OF_BOOKLIST * sizeof(int));
// Fill in values
//...
// Assign to the ivar
[aList setBookList:arr];

Then you need to free that memory when the object is destroyed:

- (void) dealloc {

    free(bookList);
    // Clean up other ivars
    [super dealloc];
}

In all, this is very like manually handling the memory of any old object. You call malloc (with an argument stating the amount of memory you want) instead of sending alloc to the class (which knows how much memory is needed), and use free instead of release to relinquish the memory. (Also note that free, since there is no reference counting, immediately marks the memory for re-use.)

*Which is essentially why reference counting was invented.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文