问题
I'm getting a segmentation fault whenever a 1 is entered at the prompt for:
print*,"where would you like to buy/sell from/into (enter first number between 1 and ", &
size(energy(:,1)),"and second number between 1 and",size(energy(1,:)),")"
So, I'm trying to create a simple program representing a market and it seems that everything else works so far, except when 1 is passed into the subroutine buy_sell through the item_choice_i or item_choice_k. I'm somewhat new at programming and I'm not sure how to fix a fault like this.
!subroutine section:
subroutine buy_sell(buyer,buyer_size,buyer_number,energy,item_choice_k,item_choice_i,exchange_ammount) !the market form has k then i
implicit none
integer,intent(in) :: item_choice_k,item_choice_i,exchange_ammount,buyer_size,buyer_number
integer,dimension(buyer_size) :: buyer !the amount the buyer has in savings
integer,intent(inout),dimension(10,10) :: energy
energy(item_choice_k,item_choice_i)=energy(item_choice_k,item_choice_i)-exchange_ammount !purchasing is thus positive exchange amount and selling is negative
buyer(buyer_number)=buyer(buyer_number)+exchange_ammount
end subroutine buy_sell
subroutine print_market(energy,k_size,i_size,buyer,buyer_size)
implicit none
integer,intent(in) :: k_size,i_size,buyer_size
integer,dimension(buyer_size) :: buyer
integer,dimension(k_size,i_size),intent(in) :: energy
integer :: k,i,l
do k=1,k_size
do i=1,i_size
print*,"the value of energy(",k,i,") is", energy(k,i)
enddo
enddo
print*," "
l=1
print*,"Buyer",l,"has",buyer(l),"energy units (user)"
do l=2,buyer_size
print*,"Buyer",l,"has",buyer(l),"energy units"
enddo
end subroutine print_market
subroutine user_buyer_interface(energy,k_size,i_size,buyer,buyer_size) !the user buyer is always the first element in the buyer list
integer,intent(in) :: k_size,i_size,buyer_size
integer,dimension(buyer_size) :: buyer
integer,dimension(k_size,i_size),intent(inout) :: energy
integer :: period,item_choice_k,item_choice_i,exchange_ammount,exchange_error,buyer1
character(len=3) :: choice_buy_sell
buyer1=buyer(1)
print*,"do you want to buy/sell this round?"
read (*,*) choice_buy_sell
if (choice_buy_sell/='yes' .or. choice_buy_sell/='no') then !stupid users, choose yes or no
do while (choice_buy_sell/='yes' .and. choice_buy_sell/='no') !beat them into submission
print*,"incorrect choice, try again."
read (*,*) choice_buy_sell
enddo
endif
if (choice_buy_sell=="yes") then !start buy/sell procedure
print*,"where would you like to buy/sell from/into (enter first number between 1 and ", &
size(energy(:,1)),"and second number between 1 and",size(energy(1,:)),")"
read (*,*) item_choice_k,item_choice_i !finds the required item in the list and records it
do while ((1>item_choice_k .or. item_choice_k>k_size) .or. (1>item_choice_i .or. item_choice_i>i_size)) !must enter available item
print*,"incorrect choice, try again."
read (*,*) item_choice_k,item_choice_i
enddo
print*,"how much do you want to buy/sell (positive for buy and negative for sell)?"
read (*,'(i10)',iostat=exchange_error) exchange_ammount !puts error associated with non integr in exchange_error, where 0 is non-error
do while (exchange_error/=0)
print*,"incorrect choice, try again."
read (*,'(i10)',iostat=exchange_error) exchange_ammount
enddo
call buy_sell(buyer,buyer_size,1,energy,item_choice_k,item_choice_i,exchange_ammount)
print*,"now let the other buyers have their turn"
else if (choice_buy_sell=="no") then
print*,"now let the other buyers have their turn"
endif
call print_market(energy,k_size,i_size,buyer,buyer_size)
end subroutine user_buyer_interface
subroutine automated_buyers(energy,k_size,i_size,buyer,buyer_size)
integer,intent(in) :: k_size,i_size,buyer_size
integer,dimension(k_size,i_size) :: energy
integer,dimension(buyer_size) :: buyer
real :: k_real,i_real,buy_real !real variables to put in random generator
integer :: h,ran_k,ran_i,ran_buy !integers taken from real random values previous
do h=2,buyer_size
call random_number(k_real)
call random_number(i_real)
call random_number(buy_real)
ran_k=floor(k_real*11)
ran_i=floor(i_real*11)
ran_buy=-5+floor(buy_real*11)
call buy_sell(buyer,buyer_size,h,energy,ran_k,ran_i,ran_buy)
enddo
end subroutine automated_buyers
!end subroutines
program market
implicit none
integer,dimension(10,10) :: energy
integer,dimension(10) :: buyer
integer :: period,k,i,l,item_choice_k,item_choice_i,exchange_ammount,exchange_error
integer :: k_size=size(energy(:,1)),i_size=size(energy(1,:)),buyer_size=size(buyer) !setup the size variables in the definition
do k=1,k_size
do i=1,i_size
energy(k,i)= 1 !setting up an array representing a market, putting in initial values
enddo
enddo
do l=1,buyer_size
buyer(l)=0
enddo
do period=1,10
call print_market(energy,k_size,i_size,buyer,buyer_size)
call user_buyer_interface(energy,k_size,i_size,buyer,buyer_size)
call automated_buyers(energy,k_size,i_size,buyer,buyer_size)
enddo
end program market
The program, run, should ask whether one wanted to buy/sell, where one wanted to buy/sell from and how much, and should progress to showing the details of the buying round. But when the program is run, where 1 is entered in selection of either dimensions of the energy array, the segmentation fault comes up. Any help would be appreciated.
回答1:
You are accessing an array out of bounds. This is one of the most common reasons for this error, and all compilers have flags to automatically detect the problem for you, and point out where it is occurring. I strongly suggest you learn how to do this with you own compiler, if you get into programming it could save you months of your life - and when testing your program it will help find errors that might otherwise go undetected. Here is how you do it with gfortran - the magic flag is -fcheck=all :
ian@eris:~/work/stackoverflow$ gfortran -O -Wall -Wextra -fcheck=all -std=f2003 -g m.f90
m.f90:42:17:
integer :: period,item_choice_k,item_choice_i,exchange_ammount,exchange_error,buyer1
1
Warning: Unused variable ‘period’ declared at (1) [-Wunused-variable]
m.f90:108:68:
integer :: period,k,i,l,item_choice_k,item_choice_i,exchange_ammount,exchange_error
1
Warning: Unused variable ‘exchange_ammount’ declared at (1) [-Wunused-variable]
m.f90:108:83:
integer :: period,k,i,l,item_choice_k,item_choice_i,exchange_ammount,exchange_error
1
Warning: Unused variable ‘exchange_error’ declared at (1) [-Wunused-variable]
m.f90:108:51:
integer :: period,k,i,l,item_choice_k,item_choice_i,exchange_ammount,exchange_error
1
Warning: Unused variable ‘item_choice_i’ declared at (1) [-Wunused-variable]
m.f90:108:37:
integer :: period,k,i,l,item_choice_k,item_choice_i,exchange_ammount,exchange_error
1
Warning: Unused variable ‘item_choice_k’ declared at (1) [-Wunused-variable]
ian@eris:~/work/stackoverflow$ gfortran -O -Wall -Wextra -fcheck=all -std=f2003 -g m.f90
m.f90:42:17:
integer :: period,item_choice_k,item_choice_i,exchange_ammount,exchange_error,buyer1
1
Warning: Unused variable ‘period’ declared at (1) [-Wunused-variable]
m.f90:108:68:
integer :: period,k,i,l,item_choice_k,item_choice_i,exchange_ammount,exchange_error
1
Warning: Unused variable ‘exchange_ammount’ declared at (1) [-Wunused-variable]
m.f90:108:83:
integer :: period,k,i,l,item_choice_k,item_choice_i,exchange_ammount,exchange_error
1
Warning: Unused variable ‘exchange_error’ declared at (1) [-Wunused-variable]
m.f90:108:51:
integer :: period,k,i,l,item_choice_k,item_choice_i,exchange_ammount,exchange_error
1
Warning: Unused variable ‘item_choice_i’ declared at (1) [-Wunused-variable]
m.f90:108:37:
integer :: period,k,i,l,item_choice_k,item_choice_i,exchange_ammount,exchange_error
1
Warning: Unused variable ‘item_choice_k’ declared at (1) [-Wunused-variable]
ian@eris:~/work/stackoverflow$ ./a.out
the value of energy( 1 1 ) is 1
the value of energy( 1 2 ) is 1
the value of energy( 1 3 ) is 1
the value of energy( 1 4 ) is 1
the value of energy( 1 5 ) is 1
the value of energy( 1 6 ) is 1
the value of energy( 1 7 ) is 1
the value of energy( 1 8 ) is 1
the value of energy( 1 9 ) is 1
the value of energy( 1 10 ) is 1
the value of energy( 2 1 ) is 1
the value of energy( 2 2 ) is 1
the value of energy( 2 3 ) is 1
the value of energy( 2 4 ) is 1
the value of energy( 2 5 ) is 1
the value of energy( 2 6 ) is 1
the value of energy( 2 7 ) is 1
the value of energy( 2 8 ) is 1
the value of energy( 2 9 ) is 1
the value of energy( 2 10 ) is 1
the value of energy( 3 1 ) is 1
the value of energy( 3 2 ) is 1
the value of energy( 3 3 ) is 1
the value of energy( 3 4 ) is 1
the value of energy( 3 5 ) is 1
the value of energy( 3 6 ) is 1
the value of energy( 3 7 ) is 1
the value of energy( 3 8 ) is 1
the value of energy( 3 9 ) is 1
the value of energy( 3 10 ) is 1
the value of energy( 4 1 ) is 1
the value of energy( 4 2 ) is 1
the value of energy( 4 3 ) is 1
the value of energy( 4 4 ) is 1
the value of energy( 4 5 ) is 1
the value of energy( 4 6 ) is 1
the value of energy( 4 7 ) is 1
the value of energy( 4 8 ) is 1
the value of energy( 4 9 ) is 1
the value of energy( 4 10 ) is 1
the value of energy( 5 1 ) is 1
the value of energy( 5 2 ) is 1
the value of energy( 5 3 ) is 1
the value of energy( 5 4 ) is 1
the value of energy( 5 5 ) is 1
the value of energy( 5 6 ) is 1
the value of energy( 5 7 ) is 1
the value of energy( 5 8 ) is 1
the value of energy( 5 9 ) is 1
the value of energy( 5 10 ) is 1
the value of energy( 6 1 ) is 1
the value of energy( 6 2 ) is 1
the value of energy( 6 3 ) is 1
the value of energy( 6 4 ) is 1
the value of energy( 6 5 ) is 1
the value of energy( 6 6 ) is 1
the value of energy( 6 7 ) is 1
the value of energy( 6 8 ) is 1
the value of energy( 6 9 ) is 1
the value of energy( 6 10 ) is 1
the value of energy( 7 1 ) is 1
the value of energy( 7 2 ) is 1
the value of energy( 7 3 ) is 1
the value of energy( 7 4 ) is 1
the value of energy( 7 5 ) is 1
the value of energy( 7 6 ) is 1
the value of energy( 7 7 ) is 1
the value of energy( 7 8 ) is 1
the value of energy( 7 9 ) is 1
the value of energy( 7 10 ) is 1
the value of energy( 8 1 ) is 1
the value of energy( 8 2 ) is 1
the value of energy( 8 3 ) is 1
the value of energy( 8 4 ) is 1
the value of energy( 8 5 ) is 1
the value of energy( 8 6 ) is 1
the value of energy( 8 7 ) is 1
the value of energy( 8 8 ) is 1
the value of energy( 8 9 ) is 1
the value of energy( 8 10 ) is 1
the value of energy( 9 1 ) is 1
the value of energy( 9 2 ) is 1
the value of energy( 9 3 ) is 1
the value of energy( 9 4 ) is 1
the value of energy( 9 5 ) is 1
the value of energy( 9 6 ) is 1
the value of energy( 9 7 ) is 1
the value of energy( 9 8 ) is 1
the value of energy( 9 9 ) is 1
the value of energy( 9 10 ) is 1
the value of energy( 10 1 ) is 1
the value of energy( 10 2 ) is 1
the value of energy( 10 3 ) is 1
the value of energy( 10 4 ) is 1
the value of energy( 10 5 ) is 1
the value of energy( 10 6 ) is 1
the value of energy( 10 7 ) is 1
the value of energy( 10 8 ) is 1
the value of energy( 10 9 ) is 1
the value of energy( 10 10 ) is 1
Buyer 1 has 0 energy units (user)
Buyer 2 has 0 energy units
Buyer 3 has 0 energy units
Buyer 4 has 0 energy units
Buyer 5 has 0 energy units
Buyer 6 has 0 energy units
Buyer 7 has 0 energy units
Buyer 8 has 0 energy units
Buyer 9 has 0 energy units
Buyer 10 has 0 energy units
do you want to buy/sell this round?
yes
where would you like to buy/sell from/into (enter first number between 1 and 10 and second number between 1 and 10 )
1
10
how much do you want to buy/sell (positive for buy and negative for sell)?
1
now let the other buyers have their turn
the value of energy( 1 1 ) is 1
the value of energy( 1 2 ) is 1
the value of energy( 1 3 ) is 1
the value of energy( 1 4 ) is 1
the value of energy( 1 5 ) is 1
the value of energy( 1 6 ) is 1
the value of energy( 1 7 ) is 1
the value of energy( 1 8 ) is 1
the value of energy( 1 9 ) is 1
the value of energy( 1 10 ) is 0
the value of energy( 2 1 ) is 1
the value of energy( 2 2 ) is 1
the value of energy( 2 3 ) is 1
the value of energy( 2 4 ) is 1
the value of energy( 2 5 ) is 1
the value of energy( 2 6 ) is 1
the value of energy( 2 7 ) is 1
the value of energy( 2 8 ) is 1
the value of energy( 2 9 ) is 1
the value of energy( 2 10 ) is 1
the value of energy( 3 1 ) is 1
the value of energy( 3 2 ) is 1
the value of energy( 3 3 ) is 1
the value of energy( 3 4 ) is 1
the value of energy( 3 5 ) is 1
the value of energy( 3 6 ) is 1
the value of energy( 3 7 ) is 1
the value of energy( 3 8 ) is 1
the value of energy( 3 9 ) is 1
the value of energy( 3 10 ) is 1
the value of energy( 4 1 ) is 1
the value of energy( 4 2 ) is 1
the value of energy( 4 3 ) is 1
the value of energy( 4 4 ) is 1
the value of energy( 4 5 ) is 1
the value of energy( 4 6 ) is 1
the value of energy( 4 7 ) is 1
the value of energy( 4 8 ) is 1
the value of energy( 4 9 ) is 1
the value of energy( 4 10 ) is 1
the value of energy( 5 1 ) is 1
the value of energy( 5 2 ) is 1
the value of energy( 5 3 ) is 1
the value of energy( 5 4 ) is 1
the value of energy( 5 5 ) is 1
the value of energy( 5 6 ) is 1
the value of energy( 5 7 ) is 1
the value of energy( 5 8 ) is 1
the value of energy( 5 9 ) is 1
the value of energy( 5 10 ) is 1
the value of energy( 6 1 ) is 1
the value of energy( 6 2 ) is 1
the value of energy( 6 3 ) is 1
the value of energy( 6 4 ) is 1
the value of energy( 6 5 ) is 1
the value of energy( 6 6 ) is 1
the value of energy( 6 7 ) is 1
the value of energy( 6 8 ) is 1
the value of energy( 6 9 ) is 1
the value of energy( 6 10 ) is 1
the value of energy( 7 1 ) is 1
the value of energy( 7 2 ) is 1
the value of energy( 7 3 ) is 1
the value of energy( 7 4 ) is 1
the value of energy( 7 5 ) is 1
the value of energy( 7 6 ) is 1
the value of energy( 7 7 ) is 1
the value of energy( 7 8 ) is 1
the value of energy( 7 9 ) is 1
the value of energy( 7 10 ) is 1
the value of energy( 8 1 ) is 1
the value of energy( 8 2 ) is 1
the value of energy( 8 3 ) is 1
the value of energy( 8 4 ) is 1
the value of energy( 8 5 ) is 1
the value of energy( 8 6 ) is 1
the value of energy( 8 7 ) is 1
the value of energy( 8 8 ) is 1
the value of energy( 8 9 ) is 1
the value of energy( 8 10 ) is 1
the value of energy( 9 1 ) is 1
the value of energy( 9 2 ) is 1
the value of energy( 9 3 ) is 1
the value of energy( 9 4 ) is 1
the value of energy( 9 5 ) is 1
the value of energy( 9 6 ) is 1
the value of energy( 9 7 ) is 1
the value of energy( 9 8 ) is 1
the value of energy( 9 9 ) is 1
the value of energy( 9 10 ) is 1
the value of energy( 10 1 ) is 1
the value of energy( 10 2 ) is 1
the value of energy( 10 3 ) is 1
the value of energy( 10 4 ) is 1
the value of energy( 10 5 ) is 1
the value of energy( 10 6 ) is 1
the value of energy( 10 7 ) is 1
the value of energy( 10 8 ) is 1
the value of energy( 10 9 ) is 1
the value of energy( 10 10 ) is 1
Buyer 1 has 1 energy units (user)
Buyer 2 has 0 energy units
Buyer 3 has 0 energy units
Buyer 4 has 0 energy units
Buyer 5 has 0 energy units
Buyer 6 has 0 energy units
Buyer 7 has 0 energy units
Buyer 8 has 0 energy units
Buyer 9 has 0 energy units
Buyer 10 has 0 energy units
At line 9 of file m.f90
Fortran runtime error: Index '0' of dimension 1 of array 'energy' below lower bound of 1
Error termination. Backtrace:
#0 0x7f0741dac2da in ???
#1 0x7f0741dacec5 in ???
#2 0x7f0741dad297 in ???
#3 0x559df7cde202 in buy_sell_
at /home/ian/work/stackoverflow/m.f90:9
#4 0x559df7cde36b in automated_buyers_
at /home/ian/work/stackoverflow/m.f90:92
#5 0x559df7cdec9d in market
at /home/ian/work/stackoverflow/m.f90:124
#6 0x559df7cdecde in main
at /home/ian/work/stackoverflow/m.f90:127
ian@eris:~/work/stackoverflow$
Looking at the traceback at the end
At line 9 of file m.f90
Fortran runtime error: Index '0' of dimension 1 of array 'energy' below lower bound of 1
Error termination. Backtrace:
#0 0x7f0741dac2da in ???
#1 0x7f0741dacec5 in ???
#2 0x7f0741dad297 in ???
#3 0x559df7cde202 in buy_sell_
at /home/ian/work/stackoverflow/m.f90:9
#4 0x559df7cde36b in automated_buyers_
at /home/ian/work/stackoverflow/m.f90:92
#5 0x559df7cdec9d in market
at /home/ian/work/stackoverflow/m.f90:124
#6 0x559df7cdecde in main
at /home/ian/work/stackoverflow/m.f90:127
You can see the issue is when buy_sell is called from automated_buyers:
subroutine automated_buyers(energy,k_size,i_size,buyer,buyer_size)
integer,intent(in) :: k_size,i_size,buyer_size
integer,dimension(k_size,i_size) :: energy
integer,dimension(buyer_size) :: buyer
real :: k_real,i_real,buy_real !real variables to put in random generator
integer :: h,ran_k,ran_i,ran_buy !integers taken from real random values previous
do h=2,buyer_size
call random_number(k_real)
call random_number(i_real)
call random_number(buy_real)
ran_k=floor(k_real*11)
ran_i=floor(i_real*11)
ran_buy=-5+floor(buy_real*11)
call buy_sell(buyer,buyer_size,h,energy,ran_k,ran_i,ran_buy)
enddo
end subroutine automated_buyers
This shows what the problem is, ran_k can take the value 0 if the random number in k_real is less than 1/11. What you probably want is
ran_k = Int( k_real * 10 ) + 1
Please learn about run time checks, they will make your life much easier, as will learning about using a debugger. But note they will slow your program down, so while you should use them when developing and debugging the code, once you are sure that there are no more bugs (ha!) you should re-compile without them as your program will then run quicker.
来源:https://stackoverflow.com/questions/53921730/where-is-the-cause-of-this-segmentation-fault-where-1-is-entered-into-the-item