質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

OS

OS(オペレーティングシステム)は、システムソフトウェアの一種であり、一般的に、ハードウェアを直接的に管理・操作する最も中心的な機能を有するソフトウェアがオペレーティングシステムとして呼ばれます。

アーキテクチャ

アーキテクチャとは、情報システム(ハードウェア、OS、アプリケーション、ネットワーク等)の設計方法、設計思想、設計思想に基づいて構築されたシステム構造をアーキテクチャと呼びます

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

4回答

11682閲覧

64bitでポインタのオーバーフローが起こるのでは??

strike1217

総合スコア651

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

OS

OS(オペレーティングシステム)は、システムソフトウェアの一種であり、一般的に、ハードウェアを直接的に管理・操作する最も中心的な機能を有するソフトウェアがオペレーティングシステムとして呼ばれます。

アーキテクチャ

アーキテクチャとは、情報システム(ハードウェア、OS、アプリケーション、ネットワーク等)の設計方法、設計思想、設計思想に基づいて構築されたシステム構造をアーキテクチャと呼びます

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2017/01/23 08:50

編集2017/01/23 10:10

ふと思ったのですが、
「ポインタに入るアドレスの値がそのポインタ型の最大値を超えたら、オーバーフローが起こるのでは??」
と・・・

確認プログラムを作成してみました。

C

1#include<stdio.h> 2 3int main() { 4 char h = 1000; // わざと 5 int n = 255; 6 long m = 4294967295; 7 printf("%d\n", h); 8 printf("char : 255 = 0x%x\n", n); 9 printf("unsigned int : 4,294,967,295 = 0x%x\n", m); 10 11 int i = 90; 12 13 char a = 'A'; 14 char *p = &a; 15 printf("&a : 0x%p, sizeof(char *) = %d Bytes, sizeof(int *) = %d Bytes\n", p, sizeof(char *), sizeof(int *)); 16 return 0; 17} 18

結果は以下のようになりました。
**-24
char : 255 = 0xff
unsigned int : 4,294,967,295 = 0xffffffff
&a : 0x0060FABF, sizeof(char ) = 4 Bytes, sizeof(int ) = 4 Bytes

int * を例に取ります。
大きさは4Byteなので 0x00000000 ~ 0xffffffff までのアドレスなら格納できることになるはずです。

以下のようなものを見つけました。
リンク内容

32bit OSなら、4GBまでなのでこれでも問題なさそうですが、64bitになるとアドレス空間が大きくなります。

例えば、メインメモリを32GB(8GB x 4スロット)積んでいたとします。
以前も質問をしたのですが、(リンク内容)1つのアプリケーションで、10億個の配列を使用した場合、12x10^9になるので、メモリは12GB搭載していないと動かない・・・ということになると思います。

これって、0xffffffff を超えるようなアドレスの値を int * に入れ込むと、オーバーフローになりませんか??

これ、やばいような気がするんですが・・・実際はどうなっているのですか??
教えてください。

[追記]
環境を追記しますね。
windows 64bit
ファイル拡張子 .c です。
visual studioでコンパイルしてみました。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

ベストアンサー

環境(32/64bit)によりポインタ型のサイズも異なります。
C/C++における整数型には気をつけよ

投稿2017/01/23 08:57

can110

総合スコア38260

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

strike1217

2017/01/23 10:11

c++ でも同じようにやってみましたが、(int *) 4bytesから変化がないです>< どうしてでしょう??
can110

2017/01/23 10:14

ビルドオプションが不明なのであてずっぽうですが、ターゲットが32bitになっているのでは?
strike1217

2017/01/23 10:15

ビルドオプションな何も入れてないですね。 visual studio は標準で32bitになってしまうんですかね?・・・
strike1217

2017/01/23 10:31

えーと、 どの方をベストアンサーにすれば良いのか迷ったのですが、高評価だったので、ベストアンサーにさせてもらいます。
guest

0

「オーバーフロー」という言葉を正しく理解していらっしゃらないように思います。

「算術オーバーフロー」は、演算の結果が、その結果を格納すべきレジスタの表せる値の範囲外になることを意味します。レジスタに格納された値はもはや期待される結果を表しませんので、オーバーフローがあったか否かを知る必要があります。

スタックのような構造では必要な記憶域の大きさが動的に変化しますが、大きさが上限に達してそれ以上利用できなくなることを、「スタックオーバーフロー」と言います。

一方、あるバッファ領域にデータを格納する際、データの長さのチェックを怠りバッファ長を超えて書き込んでしまうことを「バッファオーバーフロー」と言います。

変数 (レジスタやメモリなど) へのデータの格納の場合、格納に必要な記憶域の大きさがデータの大きさを超えていれば、正しい情報を格納できません。これはあらかじめ必要な大きさの記憶域を確保しなかったために起きる問題です。なんらかの演算の結果が期待通りでないこととは違いますし、記憶域の大きさを動的に変化させることができたわけでもありませんし、データ長のチェックが必要なわけでもありません。つまり、算術オーバーフローでも、スタックオーバーフローでも、バッファオーバーフローでもありません。

投稿2017/01/23 10:06

編集2017/01/23 10:42
ikedas

総合スコア4315

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

strike1217

2017/01/23 10:12

ありがとうございます! おへ・・・ そうなんですか!
guest

0

こんにちは。

これって、0xffffffff を超えるようなアドレスの値を int * に入れ込むと、オーバーフローになりませんか??

32ビット・ビルドしている時は当然オーバーフローします。
64ビット・ビルドならポインタも64ビットあるので余裕です。

これ、やばいような気がするんですが・・・実際はどうなっているのですか??

C/C++ではオーバーフロー/アンダーフローが問題を起こさないようにプログラムすることはプログラマの責任です。この件に関してコンパイラはあまりサポートしてくれません。

でも、メモリのあるところしかアクセスしないプログラムであれば通常は問題でないです。32ビットのポインタでボイントできないメモリを割り当てられることはありませんから。
逆に言えば、32ビット・ビルドしたプログラムは4GBytesを超えるメモリを通常の手順では使えません。だから最近は64ビットOSが良く使われます。

投稿2017/01/23 09:44

Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

strike1217

2017/01/23 10:13

visual studio は標準で、32bitビルドになっているんでしょうかね??・・・
strike1217

2017/01/23 10:23

げげげげ!! やだ! 32bitのプログラムで64bitの考察をしてしまいました。 きゃあああああ><
Chironian

2017/01/23 10:33

なるほど。たぶん64ビットOSでビルドしてたのですね。ドンマイです。
guest

0

64bit環境のgccで次のようなプログラムを動かしてみました。

C

1#include <stdio.h> 2 3int main() { 4 printf("%d %d %d %d\n", 5 (int)sizeof(int), (int)sizeof(int*), 6 (int)sizeof(size_t), (int)sizeof(intptr_t); 7}

結果は4 8 8 8となります。can110さんがおっしゃるようにintは「そのプラットフォームでの自然な語長」ではありますが「そのプラットフォームでのメモリーの空間を完全に表現できるビット数」とは定義されていません。そうした目的にはsize_t(訂正: intptr_t)が妥当と言えると思います。


訂正:
raccyさんのコメントみて気づきましたがsize_tではなくてintptr_t/uintptr_tが空間サイズを表現するのに適切な型のようでした。失礼しました。
size_tは空間の大きさを表現するものという定義ではなく配列の指標、構造のサイズ、プログラム内の最大のメモリオフセットの保持が可能という意味あいのものでほぼ空間サイズとして使えると思っていたのですがズバリintptr_t/uintptr_tの定義が空間サイズなんですね。
追記:
ついでに上のコードで"%d"でsize_t型を印字しようとしているのが怪しいので直しました。

投稿2017/01/23 09:18

編集2017/01/23 11:35
KSwordOfHaste

総合スコア18394

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

strike1217

2017/01/23 10:14

ありがとうございます Linuxでやったのですかね・・・ やはり、OSによっても異なるみたいですね。
KSwordOfHaste

2017/01/23 11:05

raccyさんのコメントを拝見しました。正直、size_tはレガシーな知識だったようですw; stackoverflowの回答や他のを見てみるとintptr_t/uintptr_tが空間の大きさを扱うには適切のようですね。 intptr_tは使ったことなかったです・・・失礼しました!
KSwordOfHaste

2017/01/23 11:28

linuxじゃなくてcygwin64でした・・・(小声)
strike1217

2017/01/23 11:38

左様でございますか!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問